mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-12-21 13:10:58 +01:00
289 lines
7.4 KiB
ObjectPascal
289 lines
7.4 KiB
ObjectPascal
unit utdirwatch;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, fpcunit, testutils, testregistry, dirwatch;
|
|
|
|
type
|
|
TChangedEntry = record
|
|
Dir : TWatchDirectoryEntry;
|
|
Events : TWatchFileEvents;
|
|
FN : String;
|
|
end;
|
|
TChangedEntryArray = Array of TChangedEntry;
|
|
|
|
{ TTestDirWatch }
|
|
|
|
TTestDirWatch= class(TTestCase)
|
|
private
|
|
FDirWatch: TDirwatch;
|
|
FTestDir: string;
|
|
FChanged: TChangedEntryArray;
|
|
FCheckCount : Integer;
|
|
FMaxLoopCount : Integer;
|
|
FDoCheckOne : TNotifyEvent;
|
|
procedure AssertChange(const Msg: String; aIndex: Integer; aEntry: TWatchDirectoryEntry; aEvents: TWatchFileEvents; const aFileName : string = '');
|
|
procedure CleanDirs(aDir: String);
|
|
procedure DoAppendFile(const aName: string);
|
|
procedure DoChange(Sender: TObject; const aEvent: TFileChangeEvent);
|
|
procedure DoCheck(sender: TObject; var aContinue: Boolean);
|
|
procedure DoCreateFile(const aName: string);
|
|
procedure DoDeleteFile(const aName: string);
|
|
procedure HandleCreateFile(Sender: TObject);
|
|
protected
|
|
procedure SetUp; override;
|
|
procedure TearDown; override;
|
|
property dirwatch : TDirwatch read FDirWatch;
|
|
Property TestDir : string Read FTestDir;
|
|
property CheckCount : Integer Read FCheckCount;
|
|
property MaxLoopCount : Integer Read FMaxLoopCount Write FMaxLoopCount;
|
|
Public
|
|
class procedure AssertEquals(const Msg: String; aExpected, aActual: TWatchFileEvents); overload;
|
|
published
|
|
procedure TestHookUp;
|
|
procedure TestAddFile;
|
|
procedure TestAppendFile;
|
|
procedure TestDeleteFile;
|
|
procedure TestLoopNoThread;
|
|
procedure TestLoopThread;
|
|
procedure TestAddFileBaseDir;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses typinfo, inifiles;
|
|
|
|
var
|
|
BaseDir : String;
|
|
|
|
procedure TTestDirWatch.CleanDirs(aDir: String);
|
|
|
|
Var
|
|
Info : TSearchRec;
|
|
lDir,lFull : String;
|
|
|
|
begin
|
|
lDir:=IncludeTrailingPathDelimiter(aDir);
|
|
If FIndFirst(lDir+AllFilesMask,sysutils.faDirectory,Info)=0 then
|
|
try
|
|
Repeat
|
|
lFull:=lDir+Info.Name;
|
|
if (Info.Attr and faDirectory)<>0 then
|
|
begin
|
|
if not ((Info.Name='.') or (Info.Name='..')) then
|
|
begin
|
|
CleanDirs(lFull);
|
|
if not RemoveDir(lFull) then
|
|
Fail('Failed to remove directory %s',[lFull])
|
|
end;
|
|
end
|
|
else if not DeleteFIle(lFull) then
|
|
Fail('Failed to remove file %s',[lFull])
|
|
until FIndNext(Info)<>0;
|
|
finally
|
|
FindClose(Info);
|
|
end;
|
|
end;
|
|
|
|
procedure TTestDirWatch.DoChange(Sender: TObject; const aEvent: TFileChangeEvent);
|
|
var
|
|
Len : Integer;
|
|
begin
|
|
len:=Length(FChanged);
|
|
SetLength(FChanged,Len+1);
|
|
FChanged[Len].Dir:=aEvent.Entry;
|
|
FChanged[Len].Events:=aEvent.Events;
|
|
FChanged[Len].FN:=aEvent.FileName;
|
|
end;
|
|
|
|
procedure TTestDirWatch.DoCheck(sender: TObject; var aContinue: Boolean);
|
|
begin
|
|
aContinue:=CheckCount<MaxLoopCount;
|
|
if (FCheckCount=0) then
|
|
if Assigned(FDoCheckOne) then
|
|
FDoCheckOne(Self);
|
|
inc(FCheckCount);
|
|
end;
|
|
|
|
procedure TTestDirWatch.TestHookUp;
|
|
begin
|
|
AssertNotNull('Have watch',Dirwatch);
|
|
AssertEquals('No watches',0,Dirwatch.Watches.Count);
|
|
AssertTrue('Have test dir',TestDir<>'');
|
|
AssertTrue('test dir exists',DirectoryExists(TestDir));
|
|
AssertEquals('No max check count',0,FMaxLoopCount);
|
|
AssertEquals('No check count',0,FCheckCount);
|
|
AssertTrue('No docheckone',FDoCheckOne=nil);
|
|
end;
|
|
|
|
procedure TTestDirWatch.DoAppendFile(const aName : string);
|
|
|
|
var
|
|
FD : THandle;
|
|
begin
|
|
FD:=FileOpen(TestDir+aName,fmOpenWrite);
|
|
try
|
|
FileSeek(FD,0,fsFromEnd);
|
|
if FileWrite(FD,aName[1],Length(aName))=-1 then
|
|
Writeln(GetLastOSError);
|
|
finally
|
|
FileClose(FD);
|
|
end;
|
|
end;
|
|
|
|
procedure TTestDirWatch.DoCreateFile(const aName : string);
|
|
|
|
var
|
|
L: TStrings;
|
|
begin
|
|
L:=TStringList.Create;
|
|
try
|
|
L.Add(aName);
|
|
L.SaveToFile(TestDir+aName);
|
|
finally
|
|
L.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TTestDirWatch.DoDeleteFile(const aName: string);
|
|
|
|
begin
|
|
If not DeleteFile(TestDir+aName) then
|
|
Fail('Failed to delete file '+TestDir+aName);
|
|
end;
|
|
|
|
procedure TTestDirWatch.HandleCreateFile(Sender: TObject);
|
|
begin
|
|
DoCreateFile('name.txt');
|
|
end;
|
|
|
|
class procedure TTestDirWatch.AssertEquals(const Msg: String; aExpected,aActual : TWatchFileEvents);
|
|
|
|
begin
|
|
AssertEquals(Msg,SetToString(PTypeInfo(TypeInfo(TWatchFileEvents)),Longint(aExpected),False),
|
|
SetToString(PTypeInfo(TypeInfo(TWatchFileEvents)),Longint(aActual),False));
|
|
end;
|
|
|
|
procedure TTestDirWatch.AssertChange(const Msg: String; aIndex: Integer; aEntry: TWatchDirectoryEntry; aEvents: TWatchFileEvents;
|
|
const aFileName: string);
|
|
var
|
|
M : String;
|
|
begin
|
|
M:=Msg+Format(' [%d]: ',[aIndex]);
|
|
AssertTrue(M+'correct index',aIndex<Length(FChanged));
|
|
AssertSame(M+'correct dir entry',aEntry,FChanged[aIndex].Dir);
|
|
AssertEquals(M+'correct changes',aEvents,FChanged[aIndex].Events);
|
|
if aFileName<>'' then
|
|
AssertEquals(M+'correct fileName',aFileName,FChanged[aIndex].FN);
|
|
end;
|
|
|
|
procedure TTestDirWatch.TestAddFile;
|
|
begin
|
|
FDirwatch.AddWatch(TestDir,[feCreate]);
|
|
FDirWatch.InitWatch;
|
|
DoCreateFile('name.txt');
|
|
AssertEquals(1,FDirWatch.Check);
|
|
AssertChange('Create',0,FDirWatch.Watches[0],[feCreate],'name.txt');
|
|
end;
|
|
|
|
procedure TTestDirWatch.TestAppendFile;
|
|
begin
|
|
FDirwatch.AddWatch(TestDir,[feModify]);
|
|
DoCreateFile('name.txt');
|
|
FDirWatch.InitWatch;
|
|
DoAppendFile('name.txt');
|
|
AssertEquals('Change detected',1,FDirWatch.Check);
|
|
AssertChange('Change detected',0,FDirWatch.Watches[0],[feModify],'name.txt');
|
|
end;
|
|
|
|
|
|
procedure TTestDirWatch.TestDeleteFile;
|
|
begin
|
|
FDirwatch.AddWatch(TestDir,[feDelete]);
|
|
DoCreateFile('name.txt');
|
|
FDirWatch.InitWatch;
|
|
DoDeleteFile('name.txt');
|
|
AssertEquals('Change detected',1,FDirWatch.Check);
|
|
AssertChange('Change detected',0,FDirWatch.Watches[0],[feDelete],'name.txt');
|
|
end;
|
|
|
|
procedure TTestDirWatch.TestLoopNoThread;
|
|
begin
|
|
FDirwatch.AddWatch(TestDir,[feCreate]);
|
|
FDirwatch.OnCheck:=@DoCheck;
|
|
FDoCheckOne:=@HandleCreateFile;
|
|
MaxLoopCount:=2;
|
|
FDirWatch.StartLoop;
|
|
AssertChange('Change detected',0,FDirWatch.Watches[0],[feCreate],'name.txt');
|
|
end;
|
|
|
|
procedure TTestDirWatch.TestLoopThread;
|
|
var
|
|
I : Integer;
|
|
begin
|
|
FDirwatch.AddWatch(TestDir,[feCreate]);
|
|
FDirwatch.Threaded:=True;
|
|
FDirWatch.StartLoop;
|
|
Sleep(50);
|
|
DoCreateFile('name.txt');
|
|
I:=0;
|
|
Repeat
|
|
Sleep(10);
|
|
CheckSynchronize;
|
|
inc(i);
|
|
until (I>=50) or (length(FChanged)>0);
|
|
AssertChange('Change detected',0,FDirWatch.Watches[0],[feCreate],'name.txt');
|
|
end;
|
|
|
|
procedure TTestDirWatch.TestAddFileBaseDir;
|
|
begin
|
|
FDirwatch.BaseDir:=TestDir;
|
|
AssertTrue('Create Subdir ',ForceDirectories(TestDir+'sub'));
|
|
FDirwatch.AddWatch('',[feCreate]);
|
|
FDirWatch.InitWatch;
|
|
DoCreateFile('sub/name.txt');
|
|
AssertEquals('Subdirs not watched',0,FDirWatch.Check);
|
|
end;
|
|
|
|
procedure TTestDirWatch.SetUp;
|
|
begin
|
|
FDirWatch:=TDirwatch.Create(Nil);
|
|
FTestDir:=IncludeTrailingPathDelimiter(BaseDir);
|
|
ForceDirectories(TestDir);
|
|
FDirWatch.OnChange:=@DoChange;
|
|
FMaxLoopCount:=0;
|
|
FCheckCount:=0;
|
|
FDoCheckOne:=Nil;
|
|
end;
|
|
|
|
procedure TTestDirWatch.TearDown;
|
|
begin
|
|
CleanDirs(TestDir);
|
|
FDirWatch.Free;
|
|
end;
|
|
|
|
procedure GetBaseDir;
|
|
|
|
var
|
|
FN : string;
|
|
begin
|
|
BaseDir:=IncludeTrailingPathDelimiter(GetTempDir)+'Dirwatch'+PathDelim;
|
|
FN:=ExtractFilePath(ParamStr(0))+'config.ini';
|
|
If FileExists(FN) then
|
|
With TMemIniFile.Create(FN) do
|
|
try
|
|
BaseDir:=ReadString('dirwatch','basedir',BaseDir);
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
|
|
initialization
|
|
GetBaseDir;
|
|
RegisterTest(TTestDirWatch);
|
|
end.
|
|
|