2
0

tcresref.pp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. unit tcresref;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, fpcunit, TypInfo, testutils, testregistry;
  6. type
  7. { TRefComponent }
  8. TRefComponent = Class(TComponent)
  9. private
  10. FRef1: TComponent;
  11. FRef2: TComponent;
  12. Published
  13. Property Ref1 : TComponent Read FRef1 Write FRef1;
  14. Property Ref2 : TComponent Read FRef2 Write FRef2;
  15. end;
  16. TRootA = Class(TRefComponent)
  17. end;
  18. TRootB = Class(TRefComponent)
  19. end;
  20. TA = Class(TRefComponent)
  21. end;
  22. TB = Class(TRefComponent)
  23. end;
  24. { TTestResolveReference }
  25. TTestResolveReference = class(TTestCase)
  26. Private
  27. RootA : TRootA;
  28. RootB : TRootB;
  29. PropA1,
  30. PropA2,
  31. PropB1,
  32. PropB2 : PPRopInfo;
  33. UnrA : TObject;
  34. UnrB : TObject;
  35. protected
  36. procedure SetUp; override;
  37. procedure TearDown; override;
  38. published
  39. procedure TestAddInst1;
  40. procedure TestAddInst2;
  41. procedure TestAddInst3;
  42. procedure TestAdd2;
  43. procedure TestAdd3;
  44. Procedure TestFixupReferenceNames1;
  45. procedure TestFixupReferenceNames2;
  46. procedure TestFixupReferenceNames3;
  47. Procedure TestFixupInstanceNames1;
  48. Procedure TestFixupInstanceNames2;
  49. procedure TestFixupInstanceNames3;
  50. procedure TestFixupInstanceNames4;
  51. procedure TestFixupInstanceNames5;
  52. procedure TestRedirectFixupReferences1;
  53. procedure TestRedirectFixupReferences2;
  54. procedure TestRedirectFixupReferences3;
  55. procedure TestRemoveFixupReferences1;
  56. procedure TestRemoveFixupReferences2;
  57. procedure TestFixupReferences1;
  58. procedure TestFixupReferences2;
  59. procedure TestFixupReferences3;
  60. end;
  61. implementation
  62. {$i sllist.inc}
  63. {$i resref.inc}
  64. { ---------------------------------------------------------------------
  65. Auxiliary routines
  66. ---------------------------------------------------------------------}
  67. // Simulate Adding RootA to unresolved instances
  68. Function RootAToResolveList(TC : TTestResolveReference) : TUnresolvedInstance;
  69. begin
  70. Result:=AddToResolveList(TC.RootA);
  71. TC.UnrA:=Result;
  72. end;
  73. // Simulate Adding RootB to unresolved instances
  74. Function RootBToResolveList(TC : TTestResolveReference) : TUnresolvedInstance;
  75. begin
  76. Result:=AddToResolveList(TC.RootB);
  77. TC.UnrB:=Result;
  78. end;
  79. // Simulate RootA.Ref1 -> RootB.A unresolved reference
  80. Function SetupARef1A(TC : TTestResolveReference) : TUnresolvedReference;
  81. begin
  82. Result:=RootAToResolveList(TC).AddReference(TC.RootA,TC.PropA1,'RootB','A');
  83. end;
  84. // Simulate RootA.Ref1 -> RootB.B unresolved reference
  85. Function SetupARef1B(TC : TTestResolveReference) : TUnresolvedReference;
  86. begin
  87. Result:=RootAToResolveList(TC).AddReference(TC.RootA,TC.PropA1,'RootB','B');
  88. end;
  89. // Simulate RootA.Ref2 -> RootB.A unresolved reference
  90. Function SetupARef2A(TC : TTestResolveReference) : TUnresolvedReference;
  91. begin
  92. Result:=RootAToResolveList(TC).AddReference(TC.RootA,TC.PropA2,'RootB','A');
  93. end;
  94. // Simulate RootA.Ref2 -> RootB.B unresolved reference
  95. Function SetupARef2B(TC : TTestResolveReference) : TUnresolvedReference;
  96. begin
  97. Result:=RootAToResolveList(TC).AddReference(TC.RootA,TC.PropA2,'RootB','B');
  98. end;
  99. // Simulate RootB.Ref2 -> RootA.B unresolved reference
  100. Function SetupBRef2B(TC : TTestResolveReference) : TUnresolvedReference;
  101. begin
  102. Result:=RootBToResolveList(TC).AddReference(TC.RootB,TC.PropB2,'RootA','B');
  103. end;
  104. Function SetupBRef1A(TC : TTestResolveReference) : TUnresolvedReference;
  105. begin
  106. Result:=RootBToResolveList(TC).AddReference(TC.RootB,TC.PropB1,'RootA','A');
  107. end;
  108. // Simulate RootB.Ref1 -> RootA.B unresolved reference
  109. Function SetupNRef1B(TC : TTestResolveReference) : TUnresolvedReference;
  110. begin
  111. Result:=RootBToResolveList(TC).AddReference(TC.RootB,TC.PropB1,'RootA','B');
  112. end;
  113. // Simulate RootA.Ref2 -> RootA.A unresolved reference
  114. Function SetupBRef2A(TC : TTestResolveReference) : TUnresolvedReference;
  115. begin
  116. Result:=RootBToResolveList(TC).AddReference(TC.RootB,TC.PropB2,'RootA','A');
  117. end;
  118. { ---------------------------------------------------------------------
  119. Search callback
  120. ---------------------------------------------------------------------}
  121. Var
  122. TI : TTestResolveReference;
  123. Function SearchRoots(Const AName : String) : TComponent;
  124. begin
  125. Result:=Nil;
  126. If Assigned(TI) then
  127. begin
  128. If CompareText(AName,'RootA')=0 then
  129. Result:=TI.RootA
  130. else If CompareText(AName,'RootB')=0 then
  131. Result:=TI.RootB;
  132. end;
  133. end;
  134. { ---------------------------------------------------------------------
  135. Setup/TearDown
  136. ---------------------------------------------------------------------}
  137. procedure TTestResolveReference.SetUp;
  138. begin
  139. TI:=Self;
  140. RegisterFindGlobalComponentProc(@SearchRoots);
  141. RootA:=TRootA.Create(Nil);
  142. RootA.Name:='RootA';
  143. With TA.Create(RootA) do
  144. Name:='A';
  145. With TB.Create(RootA) do
  146. Name:='B';
  147. RootB:=TRootB.Create(Nil);
  148. With TA.Create(RootB) do
  149. Name:='A';
  150. With TB.Create(RootB) do
  151. Name:='B';
  152. PRopA1:=GetPropInfo(TRootA,'Ref1');
  153. PRopA2:=GetPropInfo(TRootA,'Ref2');
  154. PRopB1:=GetPropInfo(TRootB,'Ref1');
  155. PRopB2:=GetPropInfo(TRootB,'Ref2');
  156. end;
  157. procedure TTestResolveReference.TearDown;
  158. begin
  159. TI:=Nil;
  160. UnRegisterFindGlobalComponentProc(@SearchRoots);
  161. FreeAndNil(NeedResolving);
  162. FreeAndNil(RootA);
  163. FreeAndNil(RootB);
  164. end;
  165. { ---------------------------------------------------------------------
  166. Actual tests
  167. ---------------------------------------------------------------------}
  168. procedure TTestResolveReference.TestAddInst1;
  169. Var
  170. A : TObject;
  171. begin
  172. A:=AddToResolveList(RootA);
  173. If Not (A is TUnresolvedInstance) then
  174. Fail('AddToResolveList returns TUnresolvedInstance');
  175. AssertSame('UNresolvedinstance.Instance is RootA',RootA,TUnresolvedInstance(A).Instance);
  176. AssertSame('UNresolvedinstance.Next is nil',Nil,TUnresolvedInstance(A).Next);
  177. end;
  178. procedure TTestResolveReference.TestAddInst2;
  179. Var
  180. A,B : TObject;
  181. begin
  182. A:=AddToResolveList(RootA);
  183. B:=AddToResolveList(RootA);
  184. AssertSame('UNresolvedinstance.Instance is RootA',A,B);
  185. end;
  186. procedure TTestResolveReference.TestAddInst3;
  187. Var
  188. A,B : TUnresolvedInstance;
  189. begin
  190. A:=AddToResolveList(RootA);
  191. B:=AddToResolveList(RootB);
  192. AssertSame('UnresolvedInstances are chained',A,B.Next);
  193. end;
  194. procedure TTestResolveReference.TestAdd2;
  195. Var
  196. R : TUnresolvedReference;
  197. begin
  198. R:=SetupARef1A(Self);
  199. If (UnrA=Nil) then
  200. Fail('UnresolvedInstance A not set');
  201. AssertSame('TUnresolvedReference FRoot is rootA',RootA,R.FRoot);
  202. AssertSame('TUnresolvedReference FPropInfo is PropA1',PropA1,R.FPropInfo);
  203. AssertEquals('TUnresolvedReference FGlobal is rootB','RootB',R.FGlobal);
  204. AssertEquals('TUnresolvedReference FRelative is A','A',R.FRelative);
  205. AssertSame('Unresolved is root object',TUnresolvedinstance(UnrA).RootUnresolved,R);
  206. end;
  207. procedure TTestResolveReference.TestAdd3;
  208. Var
  209. R1 : TUnresolvedReference;
  210. R2 : TUnresolvedReference;
  211. begin
  212. R1:=SetupARef1A(Self);
  213. R2:=SetupARef2B(Self);
  214. AssertSame('TUnresolvedReference FRoot is rootA',RootA,R2.FRoot);
  215. AssertSame('TUnresolvedReference FPropInfo is PropA2',PropA2,R2.FPropInfo);
  216. AssertEquals('TUnresolvedReference FGlobal is rootB','RootB',R2.FGlobal);
  217. AssertEquals('TUnresolvedReference FRelative is A','B',R2.FRelative);
  218. AssertSame('Unresolved references are chained',R1,R2.Next);
  219. end;
  220. procedure TTestResolveReference.TestFixupReferenceNames1;
  221. Var
  222. L : TStringList;
  223. begin
  224. SetupARef1A(Self);
  225. L:=TstringList.Create;
  226. try
  227. GetFixupReferenceNames(RootA,L);
  228. AssertEquals('Number of referenced components in root component RootA is 1',1,L.Count);
  229. AssertEquals('Root component referred to is RootB','RootB',L[0]);
  230. finally
  231. L.Free;
  232. end;
  233. end;
  234. procedure TTestResolveReference.TestFixupReferenceNames2;
  235. Var
  236. L : TStringList;
  237. begin
  238. // Should result in 1 referenced name only.
  239. SetupARef1A(Self);
  240. SetupARef2B(Self);
  241. L:=TstringList.Create;
  242. try
  243. GetFixupReferenceNames(RootA,L);
  244. AssertEquals('Number of referenced components in root component RootA is 1',1,L.Count);
  245. AssertEquals('Root component referred to is always RootB','RootB',L[0]);
  246. finally
  247. L.Free;
  248. end;
  249. end;
  250. procedure TTestResolveReference.TestFixupReferenceNames3;
  251. Var
  252. L : TStringList;
  253. begin
  254. // Should result in 1 referenced name only.
  255. SetupARef1A(Self);
  256. SetupARef2B(Self);
  257. L:=TstringList.Create;
  258. try
  259. GetFixupReferenceNames(RootB,L);
  260. AssertEquals('Number of referenced components in root component RootB is 0',0,L.Count);
  261. finally
  262. L.Free;
  263. end;
  264. end;
  265. //procedure GetFixupInstanceNames(Root: TComponent; const ReferenceRootName: string; Names: TStrings);
  266. procedure TTestResolveReference.TestFixupInstanceNames1;
  267. Var
  268. L : TStringList;
  269. begin
  270. SetupARef1A(Self);
  271. L:=TstringList.Create;
  272. try
  273. GetFixupinstanceNames(RootA,'RootB',L);
  274. AssertEquals('Number of references in RootA to component RootB is 1',1,L.Count);
  275. AssertEquals('Subcomponent of RootB referenced is A','A',L[0]);
  276. finally
  277. L.Free;
  278. end;
  279. end;
  280. procedure TTestResolveReference.TestFixupInstanceNames2;
  281. Var
  282. L : TStringList;
  283. begin
  284. SetupARef1A(Self);
  285. SetupARef2B(Self);
  286. L:=TstringList.Create;
  287. try
  288. GetFixupinstanceNames(RootA,'RootB',L);
  289. AssertEquals('Number of references in RootA to component RootB is 2',2,L.Count);
  290. If L.IndexOf('A')=-1 then
  291. Fail('A is not in list of references to RootB');
  292. If L.IndexOf('B')=-1 then
  293. Fail('B is not in list of references to RootB');
  294. finally
  295. L.Free;
  296. end;
  297. end;
  298. procedure TTestResolveReference.TestFixupInstanceNames3;
  299. Var
  300. L : TStringList;
  301. begin
  302. SetupARef1A(Self);
  303. SetupARef2B(Self);
  304. L:=TstringList.Create;
  305. try
  306. GetFixupinstanceNames(RootA,'RootA',L);
  307. AssertEquals('Number of references in RootA to component RootA is 0',0,L.Count);
  308. finally
  309. L.Free;
  310. end;
  311. end;
  312. procedure TTestResolveReference.TestFixupInstanceNames4;
  313. Var
  314. L : TStringList;
  315. begin
  316. SetupARef1A(Self);
  317. SetupARef2B(Self);
  318. L:=TstringList.Create;
  319. try
  320. GetFixupinstanceNames(RootB,'RootB',L);
  321. AssertEquals('Number of references in RootB to component RootB is 0',0,L.Count);
  322. finally
  323. L.Free;
  324. end;
  325. end;
  326. procedure TTestResolveReference.TestFixupInstanceNames5;
  327. Var
  328. L : TStringList;
  329. begin
  330. SetupARef1A(Self);
  331. SetupBRef2B(Self);
  332. L:=TstringList.Create;
  333. try
  334. GetFixupinstanceNames(RootB,'RootB',L);
  335. AssertEquals('Number of references in RootB to component RootB is 0',0,L.Count);
  336. finally
  337. L.Free;
  338. end;
  339. end;
  340. // procedure RedirectFixupReferences(Root: TComponent; const OldRootName, NewRootName: string);
  341. procedure TTestResolveReference.TestRedirectFixupReferences1;
  342. Var
  343. L : TStringList;
  344. R1 : TUnresolvedReference;
  345. R2 : TUnresolvedReference;
  346. begin
  347. R1:=SetupARef1A(Self);
  348. R2:=SetupARef2B(Self);
  349. RedirectFixupReferences(RootA,'RootB','RootC');
  350. AssertEquals('Redirected R1.Root is RootC','RootC',R1.FGLobal);
  351. AssertEquals('Redirected R1.Root is RootC','RootC',R2.FGLobal);
  352. end;
  353. procedure TTestResolveReference.TestRedirectFixupReferences2;
  354. Var
  355. L : TStringList;
  356. R1 : TUnresolvedReference;
  357. R2 : TUnresolvedReference;
  358. begin
  359. R1:=SetupARef1A(Self);
  360. R2:=SetupBRef2B(Self);
  361. RedirectFixupReferences(RootA,'RootB','RootC');
  362. AssertEquals('Redirected R1.Root is RootC','RootC',R1.FGLobal);
  363. AssertEquals('R2.Root is not redirected, remains RootA','RootA',R2.FGLobal);
  364. end;
  365. procedure TTestResolveReference.TestRedirectFixupReferences3;
  366. Var
  367. R1,R2 : TUnresolvedReference;
  368. begin
  369. R1:=SetupARef1A(Self);
  370. R2:=SetupARef2B(Self);
  371. RedirectFixupReferences(RootA,'RootC','RootQ');
  372. AssertEquals('R1.Root is not redirected, remains RootB','RootB',R1.FGLobal);
  373. AssertEquals('R2.Root is not redirected, remains RootB','RootB',R2.FGLobal);
  374. end;
  375. // procedure RemoveFixupReferences(Root: TComponent; const RootName: string);
  376. procedure TTestResolveReference.TestRemoveFixupReferences1;
  377. begin
  378. SetupARef1A(Self);
  379. SetupARef2A(Self);
  380. RemoveFixupReferences(RootA,'RootB');
  381. AssertSame('No references left',Nil,NeedResolving.Root);
  382. end;
  383. procedure TTestResolveReference.TestRemoveFixupReferences2;
  384. Var
  385. RA,RB : TUnresolvedInstance;
  386. R1,R2 : TUnresolvedReference;
  387. begin
  388. RA:=RootAToResolveList(Self);
  389. RB:=RootBToResolveList(Self);
  390. R1:=SetupARef1A(Self);
  391. R2:=SetupBRef2A(Self);
  392. RemoveFixupReferences(RootA,'RootB');
  393. AssertSame('1 reference left',RB,NeedResolving.Root);
  394. end;
  395. procedure TTestResolveReference.TestFixupReferences1;
  396. begin
  397. SetupARef1A(Self);
  398. GlobalFixupReferences;
  399. AssertSame('RootA.Ref1 resolved to RootB.A',RootB.FindComponent('A'),RootA.Ref1);
  400. AssertEquals('No more resolving needs to be done',0,NeedResolving.Count);
  401. end;
  402. procedure TTestResolveReference.TestFixupReferences2;
  403. Var
  404. RI : TUnresolvedInstance;
  405. UR : TUnresolvedReference;
  406. begin
  407. // Add Not existing
  408. RI:=RootBToResolveList(Self);
  409. UR:=RI.AddReference(RootB,PropB1,'RootC','A');
  410. // Add existing
  411. SetupARef1A(Self);
  412. GlobalFixupReferences;
  413. AssertSame('RootA.Ref1 resolved to RootB.A',RootB.FindComponent('A'),RootA.Ref1);
  414. AssertSame('Reference to RootC unresolved',RI,NeedResolving.Root);
  415. end;
  416. procedure TTestResolveReference.TestFixupReferences3;
  417. Var
  418. RI : TUnresolvedInstance;
  419. UR : TUnresolvedReference;
  420. begin
  421. // Add Not existing
  422. RI:=RootAToResolveList(Self);
  423. UR:=RI.AddReference(RootA,PropA2,'RootC','A');
  424. // Add existing
  425. SetupARef1A(Self);
  426. GlobalFixupReferences;
  427. AssertSame('RootA.Ref1 resolved to RootB.A',RootB.FindComponent('A'),RootA.Ref1);
  428. AssertSame('Reference to RootC unresolved',RI,NeedResolving.Root);
  429. AssertSame('Reference to RootC unresolved',RI.RootUnresolved,UR);
  430. end;
  431. initialization
  432. RegisterTest(TTestResolveReference);
  433. InitCriticalSection(ResolveSection);
  434. finalization
  435. DoneCriticalsection(ResolveSection);
  436. end.