tcgenericqueue.pp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. unit tcgenericqueue;
  2. {$mode objfpc}
  3. interface
  4. uses
  5. fpcunit, testregistry, Classes, SysUtils, Generics.Defaults, Generics.Collections;
  6. Type
  7. TMySimpleQueue = Class(Specialize TQueue<String>);
  8. {$IFDEF FPC}
  9. EList = EListError;
  10. {$ENDIF}
  11. { TTestSimpleQueue }
  12. TTestSimpleQueue = Class(TTestCase)
  13. Private
  14. FQueue : TMySimpleQueue;
  15. FnotifyMessage : String;
  16. FCurrentValueNotify : Integer;
  17. FExpectValues : Array of String;
  18. FExpectValueAction: Array of TCollectionNotification;
  19. procedure DoAdd(aCount: Integer; aOffset: Integer=0);
  20. procedure DoAdd2;
  21. Procedure DoneExpectValues;
  22. procedure DoGetValue(Match: String; ExceptionClass: TClass=nil);
  23. procedure DoValueNotify(ASender: TObject; {$ifdef fpc}constref{$else}const{$endif} AItem: String; AAction: TCollectionNotification);
  24. Public
  25. Procedure SetExpectValues(aMessage : string; AKeys : Array of String; AActions : Array of TCollectionNotification; DoReverse : Boolean = False);
  26. Procedure SetUp; override;
  27. Procedure TearDown; override;
  28. Property Queue : TMySimpleQueue Read FQueue;
  29. Published
  30. Procedure TestEmpty;
  31. Procedure TestAdd;
  32. Procedure TestClear;
  33. Procedure TestGetValue;
  34. Procedure TestPeek;
  35. Procedure TestDequeue;
  36. Procedure TestToArray;
  37. Procedure TestEnumerator;
  38. procedure TestValueNotification;
  39. procedure TestValueNotificationDelete;
  40. end;
  41. { TMyObject }
  42. TMyObject = Class(TObject)
  43. Private
  44. fOnDestroy : TNotifyEvent;
  45. FID : Integer;
  46. public
  47. Constructor Create(aID : Integer; aOnDestroy : TNotifyEvent);
  48. destructor destroy; override;
  49. Property ID : Integer Read FID;
  50. end;
  51. TSingleObjectQueue = Class(Specialize TObjectQueue<TMyObject>);
  52. { TTestSingleObjectQueue }
  53. TTestSingleObjectQueue = Class(TTestCase)
  54. private
  55. FOQueue: TSingleObjectQueue;
  56. FList : TFPList;
  57. procedure DoAdd(aID: Integer);
  58. procedure DoDestroy(Sender: TObject);
  59. Public
  60. Procedure SetUp; override;
  61. Procedure TearDown; override;
  62. Property Queue : TSingleObjectQueue Read FOQueue;
  63. Published
  64. Procedure TestEmpty;
  65. Procedure TestFreeOnDequeue;
  66. Procedure TestNoFreeOnDeQueue;
  67. end;
  68. implementation
  69. { TTestSingleObjectQueue }
  70. procedure TTestSingleObjectQueue.SetUp;
  71. begin
  72. FOQueue:=TSingleObjectQueue.Create(True);
  73. FList:=TFPList.Create;
  74. inherited SetUp;
  75. end;
  76. procedure TTestSingleObjectQueue.TearDown;
  77. begin
  78. FreeAndNil(FOQueue);
  79. FreeAndNil(FList);
  80. inherited TearDown;
  81. end;
  82. procedure TTestSingleObjectQueue.TestEmpty;
  83. begin
  84. AssertNotNull('Have object',Queue);
  85. AssertEquals('Have empty object',0,Queue.Count);
  86. end;
  87. procedure TTestSingleObjectQueue.DoAdd(aID : Integer);
  88. Var
  89. O : TMyObject;
  90. begin
  91. O:=TMyObject.Create(aID,@DoDestroy);
  92. FOQueue.EnQueue(O);
  93. FList.Add(O);
  94. end;
  95. procedure TTestSingleObjectQueue.DoDestroy(Sender: TObject);
  96. Var
  97. I : Integer;
  98. begin
  99. I:=FList.IndexOf(Sender);
  100. AssertTrue('Have object in Queue',I<>-1);
  101. FList.Delete(I);
  102. end;
  103. procedure TTestSingleObjectQueue.TestFreeOnDeQueue;
  104. begin
  105. DoAdd(1);
  106. AssertEquals('Have obj',1,FList.Count);
  107. Queue.Dequeue;
  108. AssertEquals('Have no obj',0,FList.Count);
  109. end;
  110. procedure TTestSingleObjectQueue.TestNoFreeOnDeQueue;
  111. begin
  112. Queue.OwnsObjects:=False;
  113. DoAdd(1);
  114. AssertEquals('Have obj',1,FList.Count);
  115. Queue.DeQueue;
  116. AssertEquals('Have obj',1,FList.Count);
  117. end;
  118. { TMyObject }
  119. constructor TMyObject.Create(aID: Integer; aOnDestroy: TNotifyEvent);
  120. begin
  121. FOnDestroy:=aOnDestroy;
  122. FID:=AID;
  123. end;
  124. destructor TMyObject.destroy;
  125. begin
  126. if Assigned(FOnDestroy) then
  127. FOnDestroy(Self);
  128. inherited destroy;
  129. end;
  130. { TTestSimpleQueue }
  131. procedure TTestSimpleQueue.SetUp;
  132. begin
  133. inherited SetUp;
  134. FQueue:=TMySimpleQueue.Create;
  135. FCurrentValueNotify:=0;
  136. FExpectValues:=[];
  137. FExpectValueAction:=[];
  138. end;
  139. procedure TTestSimpleQueue.TearDown;
  140. begin
  141. // So we don't get clear messages
  142. FQueue.OnNotify:=Nil;
  143. FreeAndNil(FQueue);
  144. inherited TearDown;
  145. end;
  146. procedure TTestSimpleQueue.TestEmpty;
  147. begin
  148. AssertNotNull('Have dictionary',Queue);
  149. AssertEquals('empty dictionary',0,Queue.Count);
  150. end;
  151. procedure TTestSimpleQueue.DoAdd(aCount : Integer; aOffset : Integer=0);
  152. Var
  153. I : Integer;
  154. begin
  155. if aOffset=-1 then
  156. aOffset:=Queue.Count;
  157. For I:=aOffset+1 to aOffset+aCount do
  158. Queue.EnQueue(IntToStr(i));
  159. end;
  160. procedure TTestSimpleQueue.TestAdd;
  161. begin
  162. DoAdd(1);
  163. AssertEquals('Count OK',1,Queue.Count);
  164. DoAdd(1,1);
  165. AssertEquals('Count OK',2,Queue.Count);
  166. end;
  167. procedure TTestSimpleQueue.TestClear;
  168. begin
  169. DoAdd(3);
  170. AssertEquals('Count OK',3,Queue.Count);
  171. Queue.Clear;
  172. AssertEquals('Count after clear OK',0,Queue.Count);
  173. end;
  174. procedure TTestSimpleQueue.DoGetValue(Match: String; ExceptionClass: TClass);
  175. Var
  176. EC : TClass;
  177. A,EM : String;
  178. begin
  179. EC:=Nil;
  180. try
  181. A:=Queue.DeQueue;
  182. except
  183. On E : Exception do
  184. begin
  185. EC:=E.ClassType;
  186. EM:=E.Message;
  187. end
  188. end;
  189. if ExceptionClass=Nil then
  190. begin
  191. if EC<>Nil then
  192. Fail('Got exception '+EC.ClassName+' with message: '+EM);
  193. AssertEquals('Value is correct',Match,A)
  194. end
  195. else
  196. begin
  197. if EC=Nil then
  198. Fail('Expected exception '+ExceptionClass.ClassName+' but got none');
  199. if EC<>ExceptionClass then
  200. Fail('Expected exception class '+ExceptionClass.ClassName+' but got '+EC.ClassName+' with message '+EM);
  201. end;
  202. end;
  203. procedure TTestSimpleQueue.DoValueNotify(ASender: TObject; {$ifdef fpc}constref{$else}const{$endif} AItem: String; AAction: TCollectionNotification);
  204. begin
  205. // Writeln(FnotifyMessage+' value Notification',FCurrentValueNotify);
  206. AssertSame(FnotifyMessage+' value Correct sender', FQueue,aSender);
  207. if (FCurrentValueNotify>=Length(FExpectValues)) then
  208. Fail(FnotifyMessage+' Too many value notificiations');
  209. AssertEquals(FnotifyMessage+' Notification value no '+IntToStr(FCurrentValueNotify),FExpectValues[FCurrentValueNotify],aItem);
  210. Inc(FCurrentValueNotify);
  211. end;
  212. procedure TTestSimpleQueue.SetExpectValues(aMessage: string; AKeys: array of String;
  213. AActions: array of TCollectionNotification; DoReverse: Boolean);
  214. Var
  215. I,L : integer;
  216. begin
  217. FnotifyMessage:=aMessage;
  218. FCurrentValueNotify:=0;
  219. L:=Length(aKeys);
  220. AssertEquals('SetExpectValues: Lengths arrays equal',l,Length(aActions));
  221. SetLength(FExpectValues,L);
  222. SetLength(FExpectValueAction,L);
  223. Dec(L);
  224. if DoReverse then
  225. For I:=0 to L do
  226. begin
  227. FExpectValues[L-i]:=AKeys[i];
  228. FExpectValueAction[L-i]:=AActions[I];
  229. end
  230. else
  231. For I:=0 to L do
  232. begin
  233. FExpectValues[i]:=AKeys[i];
  234. FExpectValueAction[i]:=AActions[I];
  235. end;
  236. end;
  237. procedure TTestSimpleQueue.TestGetValue;
  238. Var
  239. I : integer;
  240. begin
  241. DoAdd(3);
  242. For I:=1 to 3 do
  243. DoGetValue(IntToStr(I));
  244. DoGetValue('4',EArgumentOutOfRangeException);
  245. end;
  246. procedure TTestSimpleQueue.TestPeek;
  247. Var
  248. I : integer;
  249. begin
  250. DoAdd(3);
  251. For I:=1 to 3 do
  252. begin
  253. AssertEquals('Peek ',IntToStr(I),FQueue.Peek);
  254. DoGetValue(IntToStr(I));
  255. end;
  256. end;
  257. procedure TTestSimpleQueue.DoAdd2;
  258. begin
  259. Queue.Enqueue('A new 2');
  260. end;
  261. procedure TTestSimpleQueue.DoneExpectValues;
  262. begin
  263. AssertEquals(FnotifyMessage+' Expected number of values seen',Length(FExpectValues),FCurrentValueNotify);
  264. end;
  265. procedure TTestSimpleQueue.TestDequeue;
  266. begin
  267. DoAdd(3);
  268. AssertEquals('1',Queue.Dequeue);
  269. AssertEquals('Count',2,Queue.Count);
  270. end;
  271. procedure TTestSimpleQueue.TestToArray;
  272. Var
  273. A : specialize TArray<String>;
  274. I : Integer;
  275. SI : String;
  276. begin
  277. DoAdd(3);
  278. A:=Queue.ToArray;
  279. AssertEquals('Length Ok',3,Length(A));
  280. For I:=1 to 3 do
  281. begin
  282. SI:=IntToStr(I);
  283. AssertEquals('Value '+SI,SI,A[i-1]);
  284. end;
  285. end;
  286. procedure TTestSimpleQueue.TestEnumerator;
  287. Var
  288. A : String;
  289. I : Integer;
  290. SI : String;
  291. begin
  292. DoAdd(3);
  293. I:=1;
  294. For A in Queue do
  295. begin
  296. SI:=IntToStr(I);
  297. AssertEquals('Value '+SI,SI,A);
  298. Inc(I);
  299. end;
  300. end;
  301. procedure TTestSimpleQueue.TestValueNotification;
  302. begin
  303. Queue.OnNotify:=@DoValueNotify;
  304. SetExpectValues('Add',['1','2','3'],[cnAdded,cnAdded,cnAdded]);
  305. DoAdd(3);
  306. DoneExpectValues;
  307. end;
  308. procedure TTestSimpleQueue.TestValueNotificationDelete;
  309. begin
  310. DoAdd(3);
  311. Queue.OnNotify:=@DoValueNotify;
  312. SetExpectValues('Clear',['1','2','3'],[cnRemoved,cnRemoved,cnRemoved],{$IFDEF FPC}true{$ELSE}False{$endif});
  313. Queue.Clear;
  314. DoneExpectValues;
  315. end;
  316. begin
  317. RegisterTests([ TTestSimpleQueue,TTestSingleObjectQueue]);
  318. end.