tests.rtti.pas 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582
  1. unit tests.rtti;
  2. {$ifdef fpc}
  3. {$mode objfpc}{$H+}
  4. {$modeswitch advancedrecords}
  5. {$endif}
  6. interface
  7. uses
  8. {$IFDEF FPC}
  9. fpcunit,testregistry, testutils,
  10. {$ELSE FPC}
  11. TestFramework,
  12. {$ENDIF FPC}
  13. Classes, SysUtils, typinfo,
  14. Rtti;
  15. type
  16. { TTestRTTI }
  17. TTestRTTI= class(TTestCase)
  18. published
  19. //procedure GetTypes;
  20. procedure GetTypeInteger;
  21. procedure GetTypePointer;
  22. procedure GetClassProperties;
  23. procedure GetClassPropertiesValue;
  24. procedure TestTRttiTypeProperties;
  25. procedure TestPropGetValueString;
  26. procedure TestPropGetValueInteger;
  27. procedure TestPropGetValueBoolean;
  28. procedure TestPropGetValueShortString;
  29. procedure TestPropGetValueProcString;
  30. procedure TestPropGetValueProcInteger;
  31. procedure TestPropGetValueProcBoolean;
  32. procedure TestPropGetValueProcShortString;
  33. procedure TestPropGetValueObject;
  34. procedure TestPropGetValueInterface;
  35. procedure TestPropGetValueFloat;
  36. procedure TestPropGetValueDynArray;
  37. procedure TestPropGetValueEnumeration;
  38. procedure TestPropGetValueChars;
  39. procedure TestPropSetValueString;
  40. procedure TestPropSetValueInteger;
  41. procedure TestPropSetValueBoolean;
  42. procedure TestPropSetValueShortString;
  43. procedure TestPropSetValueObject;
  44. procedure TestPropSetValueInterface;
  45. procedure TestPropSetValueFloat;
  46. procedure TestPropSetValueDynArray;
  47. procedure TestPropSetValueEnumeration;
  48. procedure TestPropSetValueChars;
  49. procedure TestGetValueStringCastError;
  50. procedure TestGetIsReadable;
  51. procedure TestIsWritable;
  52. procedure TestGetAttribute;
  53. procedure TestInterface;
  54. {$ifdef fpc}
  55. procedure TestInterfaceRaw;
  56. {$endif}
  57. procedure TestArray;
  58. procedure TestDynArray;
  59. procedure TestProcVar;
  60. procedure TestMethod;
  61. procedure TestRawThunk;
  62. private
  63. {$ifndef fpc}
  64. procedure Ignore(const aMsg: String);
  65. {$endif}
  66. end;
  67. implementation
  68. uses
  69. Tests.Rtti.Util, tests.rtti.types;
  70. { Note: GetTypes currently only returns those types that had been acquired using
  71. GetType, so GetTypes itself can't be really tested currently }
  72. (*procedure TTestRTTI.GetTypes;
  73. var
  74. LContext: TRttiContext;
  75. LType: TRttiType;
  76. IsTestCaseClassFound: boolean;
  77. begin
  78. LContext := TRttiContext.Create;
  79. { Enumerate all types declared in the application }
  80. for LType in LContext.GetTypes() do
  81. begin
  82. if LType.Name='TTestRTTI' then
  83. IsTestCaseClassFound:=true;
  84. end;
  85. LContext.Free;
  86. CheckTrue(IsTestCaseClassFound, 'RTTI information does not contain class of testcase.');
  87. end;*)
  88. {$ifndef fpc}
  89. procedure TTestRTTI.Ignore(const aMsg: string);
  90. begin
  91. { empty }
  92. end;
  93. {$endif}
  94. procedure TTestRTTI.TestGetValueStringCastError;
  95. var
  96. ATestClass : TTestValueClass;
  97. c: TRttiContext;
  98. ARttiType: TRttiType;
  99. AValue: TValue;
  100. i: integer;
  101. HadException: boolean;
  102. begin
  103. c := TRttiContext.Create;
  104. try
  105. ATestClass := TTestValueClass.Create;
  106. ATestClass.AString := '12';
  107. try
  108. ARttiType := c.GetType(ATestClass.ClassInfo);
  109. AValue := ARttiType.GetProperty('astring').GetValue(ATestClass);
  110. HadException := false;
  111. try
  112. i := AValue.AsInteger;
  113. except
  114. on E: Exception do
  115. if E.ClassType=EInvalidCast then
  116. HadException := true;
  117. end;
  118. Check(HadException, 'No or invalid exception on invalid cast');
  119. finally
  120. AtestClass.Free;
  121. end;
  122. finally
  123. c.Free;
  124. end;
  125. end;
  126. procedure TTestRTTI.TestGetIsReadable;
  127. var
  128. c: TRttiContext;
  129. ARttiType: TRttiType;
  130. AProperty: TRttiProperty;
  131. begin
  132. c := TRttiContext.Create;
  133. try
  134. ARttiType := c.GetType(TTestValueClass);
  135. AProperty := ARttiType.GetProperty('aBoolean');
  136. CheckEquals(AProperty.IsReadable, true);
  137. AProperty := ARttiType.GetProperty('aGetBoolean');
  138. CheckEquals(AProperty.IsReadable, true);
  139. AProperty := ARttiType.GetProperty('aWriteOnly');
  140. CheckEquals(AProperty.IsReadable, False);
  141. finally
  142. c.Free;
  143. end;
  144. end;
  145. procedure TTestRTTI.TestIsWritable;
  146. var
  147. c: TRttiContext;
  148. ARttiType: TRttiType;
  149. AProperty: TRttiProperty;
  150. begin
  151. c := TRttiContext.Create;
  152. try
  153. ARttiType := c.GetType(TTestValueClass);
  154. AProperty := ARttiType.GetProperty('aBoolean');
  155. CheckEquals(AProperty.IsWritable, true);
  156. AProperty := ARttiType.GetProperty('aGetBoolean');
  157. CheckEquals(AProperty.IsWritable, false);
  158. AProperty := ARttiType.GetProperty('aWriteOnly');
  159. CheckEquals(AProperty.IsWritable, True);
  160. finally
  161. c.Free;
  162. end;
  163. end;
  164. procedure TTestRTTI.TestGetAttribute;
  165. // TMyAnnotatedClass
  166. // TMyAttribute
  167. var
  168. c: TRttiContext;
  169. aType: TRttiType;
  170. aClass : TMyAnnotatedClass;
  171. custAttr : TCustomAttribute;
  172. myAttr : TMyAttribute absolute custattr;
  173. begin
  174. aType:=nil;
  175. custAttr:=Nil;
  176. c := TRttiContext.Create;
  177. try
  178. aClass:=TMyAnnotatedClass.Create;
  179. aType := c.GetType(aClass.ClassInfo);
  180. custAttr:=aType.GetAttribute(TMyAttribute);
  181. CheckEquals(custAttr.ClassType,TMyAttribute,'Correct class');
  182. CheckEquals('something',MyAttr.value,'Correct value');
  183. finally
  184. aClass.Free;
  185. // custAttr.Free;
  186. C.Free;
  187. end;
  188. end;
  189. procedure TTestRTTI.TestPropGetValueBoolean;
  190. var
  191. ATestClass : TTestValueClass;
  192. c: TRttiContext;
  193. ARttiType: TRttiType;
  194. AProperty: TRttiProperty;
  195. AValue: TValue;
  196. begin
  197. c := TRttiContext.Create;
  198. try
  199. ATestClass := TTestValueClass.Create;
  200. ATestClass.ABoolean := true;
  201. try
  202. ARttiType := c.GetType(ATestClass.ClassInfo);
  203. Check(assigned(ARttiType));
  204. AProperty := ARttiType.GetProperty('aBoolean');
  205. AValue := AProperty.GetValue(ATestClass);
  206. CheckEquals(true,AValue.AsBoolean);
  207. ATestClass.ABoolean := false;
  208. CheckEquals(true, AValue.AsBoolean);
  209. CheckEquals('True', AValue.ToString);
  210. CheckEquals(True, AValue.IsOrdinal);
  211. CheckEquals(1, AValue.AsOrdinal);
  212. finally
  213. AtestClass.Free;
  214. end;
  215. CheckEquals(True,AValue.AsBoolean);
  216. finally
  217. c.Free;
  218. end;
  219. end;
  220. procedure TTestRTTI.TestPropGetValueShortString;
  221. var
  222. ATestClass : TTestValueClass;
  223. c: TRttiContext;
  224. ARttiType: TRttiType;
  225. AProperty: TRttiProperty;
  226. AValue: TValue;
  227. begin
  228. c := TRttiContext.Create;
  229. try
  230. ATestClass := TTestValueClass.Create;
  231. ATestClass.AShortString := 'Hello World';
  232. try
  233. ARttiType := c.GetType(ATestClass.ClassInfo);
  234. Check(assigned(ARttiType));
  235. AProperty := ARttiType.GetProperty('aShortString');
  236. AValue := AProperty.GetValue(ATestClass);
  237. CheckEquals('Hello World',AValue.AsString);
  238. ATestClass.AShortString := 'Foobar';
  239. CheckEquals('Hello World', AValue.AsString);
  240. CheckEquals(False, AValue.IsOrdinal);
  241. CheckEquals(False, AValue.IsObject);
  242. CheckEquals(False, AValue.IsArray);
  243. CheckEquals(False, AValue.IsClass);
  244. finally
  245. AtestClass.Free;
  246. end;
  247. CheckEquals('Hello World',AValue.AsString);
  248. finally
  249. c.Free;
  250. end;
  251. end;
  252. procedure TTestRTTI.TestPropGetValueInteger;
  253. var
  254. ATestClass : TTestValueClass;
  255. c: TRttiContext;
  256. ARttiType: TRttiType;
  257. AProperty: TRttiProperty;
  258. AValue: TValue;
  259. begin
  260. c := TRttiContext.Create;
  261. try
  262. ATestClass := TTestValueClass.Create;
  263. ATestClass.AInteger := 472349;
  264. try
  265. ARttiType := c.GetType(ATestClass.ClassInfo);
  266. Check(assigned(ARttiType));
  267. AProperty := ARttiType.GetProperty('ainteger');
  268. AValue := AProperty.GetValue(ATestClass);
  269. CheckEquals(472349,AValue.AsInteger);
  270. ATestClass.AInteger := 12;
  271. CheckEquals(472349, AValue.AsInteger);
  272. CheckEquals('472349', AValue.ToString);
  273. CheckEquals(True, AValue.IsOrdinal);
  274. finally
  275. AtestClass.Free;
  276. end;
  277. CheckEquals(472349,AValue.AsInteger);
  278. finally
  279. c.Free;
  280. end;
  281. end;
  282. procedure TTestRTTI.TestPropGetValueString;
  283. var
  284. ATestClass : TTestValueClass;
  285. c: TRttiContext;
  286. ARttiType: TRttiType;
  287. AProperty: TRttiProperty;
  288. AValue: TValue;
  289. i: int64;
  290. begin
  291. c := TRttiContext.Create;
  292. try
  293. ATestClass := TTestValueClass.Create;
  294. ATestClass.AString := 'Hello World';
  295. try
  296. ARttiType := c.GetType(ATestClass.ClassInfo);
  297. Check(assigned(ARttiType));
  298. AProperty := ARttiType.GetProperty('astring');
  299. AValue := AProperty.GetValue(ATestClass);
  300. CheckEquals('Hello World',AValue.AsString);
  301. ATestClass.AString := 'Goodbye World';
  302. CheckEquals('Hello World',AValue.AsString);
  303. CheckEquals('Hello World',AValue.ToString);
  304. Check(TypeInfo(string)=AValue.TypeInfo);
  305. Check(AValue.TypeData=GetTypeData(AValue.TypeInfo));
  306. Check(AValue.IsEmpty=false);
  307. Check(AValue.IsObject=false);
  308. Check(AValue.IsClass=false);
  309. CheckEquals(AValue.IsOrdinal, false);
  310. CheckEquals(AValue.TryAsOrdinal(i), false);
  311. CheckEquals(AValue.IsType(TypeInfo(string)), true);
  312. CheckEquals(AValue.IsType(TypeInfo(integer)), false);
  313. CheckEquals(AValue.IsArray, false);
  314. finally
  315. AtestClass.Free;
  316. end;
  317. CheckEquals('Hello World',AValue.AsString);
  318. finally
  319. c.Free;
  320. end;
  321. end;
  322. procedure TTestRTTI.TestPropGetValueProcBoolean;
  323. var
  324. ATestClass : TTestValueClass;
  325. c: TRttiContext;
  326. ARttiType: TRttiType;
  327. AProperty: TRttiProperty;
  328. AValue: TValue;
  329. begin
  330. c := TRttiContext.Create;
  331. try
  332. ATestClass := TTestValueClass.Create;
  333. ATestClass.ABoolean := true;
  334. try
  335. ARttiType := c.GetType(ATestClass.ClassInfo);
  336. Check(assigned(ARttiType));
  337. AProperty := ARttiType.GetProperty('aGetBoolean');
  338. AValue := AProperty.GetValue(ATestClass);
  339. CheckEquals(true,AValue.AsBoolean);
  340. finally
  341. AtestClass.Free;
  342. end;
  343. CheckEquals(True,AValue.AsBoolean);
  344. finally
  345. c.Free;
  346. end;
  347. end;
  348. procedure TTestRTTI.TestPropGetValueProcShortString;
  349. var
  350. ATestClass : TTestValueClass;
  351. c: TRttiContext;
  352. ARttiType: TRttiType;
  353. AProperty: TRttiProperty;
  354. AValue: TValue;
  355. begin
  356. c := TRttiContext.Create;
  357. try
  358. ATestClass := TTestValueClass.Create;
  359. ATestClass.AShortString := 'Hello World';
  360. try
  361. ARttiType := c.GetType(ATestClass.ClassInfo);
  362. Check(assigned(ARttiType));
  363. AProperty := ARttiType.GetProperty('aGetShortString');
  364. AValue := AProperty.GetValue(ATestClass);
  365. CheckEquals('Hello World',AValue.AsString);
  366. finally
  367. AtestClass.Free;
  368. end;
  369. CheckEquals('Hello World',AValue.AsString);
  370. finally
  371. c.Free;
  372. end;
  373. end;
  374. procedure TTestRTTI.TestPropGetValueObject;
  375. var
  376. ATestClass : TTestValueClass;
  377. c: TRttiContext;
  378. ARttiType: TRttiType;
  379. AProperty: TRttiProperty;
  380. AValue: TValue;
  381. O: TObject;
  382. begin
  383. c := TRttiContext.Create;
  384. O := TObject.Create;
  385. try
  386. ATestClass := TTestValueClass.Create;
  387. ATestClass.AObject := O;
  388. try
  389. ARttiType := c.GetType(ATestClass.ClassInfo);
  390. Check(assigned(ARttiType));
  391. AProperty := ARttiType.GetProperty('AObject');
  392. AValue := AProperty.GetValue(ATestClass);
  393. CheckEquals(O.GetHashCode, AValue.AsObject.GetHashCode);
  394. finally
  395. AtestClass.Free;
  396. end;
  397. CheckEquals(O.GetHashCode, AValue.AsObject.GetHashCode);
  398. finally
  399. c.Free;
  400. O.Free;
  401. end;
  402. end;
  403. procedure TTestRTTI.TestPropGetValueInterface;
  404. var
  405. ATestClass : TTestValueClass;
  406. c: TRttiContext;
  407. ARttiType: TRttiType;
  408. AProperty: TRttiProperty;
  409. AValue: TValue;
  410. i: IInterface;
  411. begin
  412. c := TRttiContext.Create;
  413. i := TInterfacedObject.Create;
  414. try
  415. ATestClass := TTestValueClass.Create;
  416. ATestClass.AUnknown := i;
  417. try
  418. ARttiType := c.GetType(ATestClass.ClassInfo);
  419. Check(assigned(ARttiType));
  420. AProperty := ARttiType.GetProperty('AUnknown');
  421. AValue := AProperty.GetValue(ATestClass);
  422. Check(i = AValue.AsInterface);
  423. finally
  424. AtestClass.Free;
  425. end;
  426. Check(i = AValue.AsInterface);
  427. finally
  428. c.Free;
  429. end;
  430. end;
  431. procedure TTestRTTI.TestPropGetValueFloat;
  432. var
  433. ATestClass : TTestValueClass;
  434. c: TRttiContext;
  435. ARttiType: TRttiType;
  436. AProperty: TRttiProperty;
  437. AValueS, AValueD, AValueE, AValueC, AValueCm: TValue;
  438. begin
  439. c := TRttiContext.Create;
  440. try
  441. ATestClass := TTestValueClass.Create;
  442. ATestClass.ASingle := 1.1;
  443. ATestClass.ADouble := 2.2;
  444. ATestClass.AExtended := 3.3;
  445. ATestClass.ACurrency := 4;
  446. ATestClass.AComp := 5;
  447. try
  448. ARttiType := c.GetType(ATestClass.ClassInfo);
  449. Check(assigned(ARttiType));
  450. AProperty := ARttiType.GetProperty('ASingle');
  451. AValueS := AProperty.GetValue(ATestClass);
  452. CheckEquals(1.1, AValueS.AsExtended, 0.001);
  453. AProperty := ARttiType.GetProperty('ADouble');
  454. AValueD := AProperty.GetValue(ATestClass);
  455. CheckEquals(2.2, AValueD.AsExtended, 0.001);
  456. AProperty := ARttiType.GetProperty('AExtended');
  457. AValueE := AProperty.GetValue(ATestClass);
  458. CheckEquals(3.3, AValueE.AsExtended, 0.001);
  459. AProperty := ARttiType.GetProperty('ACurrency');
  460. AValueC := AProperty.GetValue(ATestClass);
  461. CheckEquals(4.0, AValueC.AsExtended, 0.001);
  462. AProperty := ARttiType.GetProperty('AComp');
  463. AValueCm := AProperty.GetValue(ATestClass);
  464. CheckEquals(5.0, AValueCm.AsExtended, 0.001);
  465. finally
  466. AtestClass.Free;
  467. end;
  468. CheckEquals(1.1, AValueS.AsExtended, 0.001);
  469. CheckEquals(2.2, AValueD.AsExtended, 0.001);
  470. CheckEquals(3.3, AValueE.AsExtended, 0.001);
  471. CheckEquals(4.0, AValueC.AsExtended, 0.001);
  472. CheckEquals(5.0, AValueCm.AsExtended, 0.001);
  473. finally
  474. c.Free;
  475. end;
  476. end;
  477. procedure TTestRTTI.TestPropGetValueDynArray;
  478. var
  479. ATestClass : TTestValueClass;
  480. c: TRttiContext;
  481. ARttiType: TRttiType;
  482. AProperty: TRttiProperty;
  483. AValue: TValue;
  484. A: TTestDynArray;
  485. begin
  486. c := TRttiContext.Create;
  487. A := [1, 2, 3, 4];
  488. try
  489. ATestClass := TTestValueClass.Create;
  490. ATestClass.AArray := A;
  491. try
  492. ARttiType := c.GetType(ATestClass.ClassInfo);
  493. Check(assigned(ARttiType));
  494. AProperty := ARttiType.GetProperty('AArray');
  495. AValue := AProperty.GetValue(ATestClass);
  496. CheckEquals(A[0], AValue.GetArrayElement(0).AsInteger);
  497. CheckEquals(A[1], AValue.GetArrayElement(1).AsInteger);
  498. CheckEquals(A[2], AValue.GetArrayElement(2).AsInteger);
  499. CheckEquals(A[3], AValue.GetArrayElement(3).AsInteger);
  500. finally
  501. AtestClass.Free;
  502. end;
  503. finally
  504. c.Free;
  505. end;
  506. end;
  507. procedure TTestRTTI.TestPropGetValueEnumeration;
  508. var
  509. ATestClass : TTestValueClass;
  510. c: TRttiContext;
  511. ARttiType: TRttiType;
  512. AProperty: TRttiProperty;
  513. AValue: TValue;
  514. begin
  515. c := TRttiContext.Create;
  516. try
  517. ATestClass := TTestValueClass.Create;
  518. ATestClass.AEnumeration := en3;
  519. try
  520. ARttiType := c.GetType(ATestClass.ClassInfo);
  521. Check(assigned(ARttiType));
  522. AProperty := ARttiType.GetProperty('AEnumeration');
  523. AValue := AProperty.GetValue(ATestClass);
  524. CheckEquals(Ord(en3),AValue.AsOrdinal);
  525. ATestClass.AEnumeration := en1;
  526. CheckEquals(Ord(en3), AValue.AsOrdinal);
  527. CheckEquals('en3', AValue.ToString);
  528. CheckEquals(True, AValue.IsOrdinal);
  529. finally
  530. AtestClass.Free;
  531. end;
  532. CheckEquals(Ord(en3),AValue.AsOrdinal);
  533. finally
  534. c.Free;
  535. end;
  536. end;
  537. procedure TTestRTTI.TestPropGetValueChars;
  538. var
  539. ATestClass : TTestValueClass;
  540. c: TRttiContext;
  541. ARttiType: TRttiType;
  542. AProperty: TRttiProperty;
  543. AValueC, AValueW: TValue;
  544. begin
  545. c := TRttiContext.Create;
  546. try
  547. ATestClass := TTestValueClass.Create;
  548. ATestClass.AChar := 'C';
  549. ATestClass.AWideChar := 'W';
  550. try
  551. ARttiType := c.GetType(ATestClass.ClassInfo);
  552. Check(assigned(ARttiType));
  553. AProperty := ARttiType.GetProperty('AChar');
  554. AValueC := AProperty.GetValue(ATestClass);
  555. CheckEquals('C',AValueC.AsAnsiChar);
  556. ATestClass.AChar := 'N';
  557. CheckEquals('C', AValueC.AsAnsiChar);
  558. CheckEquals('C', AValueC.ToString);
  559. CheckEquals(True, AValueC.IsOrdinal);
  560. AProperty := ARttiType.GetProperty('AWideChar');
  561. AValueW := AProperty.GetValue(ATestClass);
  562. CheckEquals('W',AValueW.AsWideChar);
  563. ATestClass.AWideChar := 'Z';
  564. CheckEquals('W', AValueW.AsWideChar);
  565. CheckEquals('W', AValueW.ToString);
  566. CheckEquals(True, AValueW.IsOrdinal);
  567. finally
  568. AtestClass.Free;
  569. end;
  570. CheckEquals('C',AValueC.AsAnsiChar);
  571. CheckEquals('W',AValueW.AsWideChar);
  572. finally
  573. c.Free;
  574. end;
  575. end;
  576. procedure TTestRTTI.TestPropSetValueString;
  577. var
  578. ATestClass : TTestValueClass;
  579. c: TRttiContext;
  580. ARttiType: TRttiType;
  581. AProperty: TRttiProperty;
  582. AValue: TValue;
  583. s: string;
  584. begin
  585. c := TRttiContext.Create;
  586. try
  587. ATestClass := TTestValueClass.Create;
  588. try
  589. ARttiType := c.GetType(ATestClass.ClassInfo);
  590. AProperty := ARttiType.GetProperty('astring');
  591. s := 'ipse lorem or something like that';
  592. TValue.Make(@s, TypeInfo(string), AValue);
  593. AProperty.SetValue(ATestClass, AValue);
  594. CheckEquals(ATestClass.AString, s);
  595. s := 'Another string';
  596. CheckEquals(ATestClass.AString, 'ipse lorem or something like that');
  597. finally
  598. AtestClass.Free;
  599. end;
  600. finally
  601. c.Free;
  602. end;
  603. end;
  604. procedure TTestRTTI.TestPropSetValueInteger;
  605. var
  606. ATestClass : TTestValueClass;
  607. c: TRttiContext;
  608. ARttiType: TRttiType;
  609. AProperty: TRttiProperty;
  610. AValue: TValue;
  611. i: integer;
  612. begin
  613. c := TRttiContext.Create;
  614. try
  615. ATestClass := TTestValueClass.Create;
  616. try
  617. ARttiType := c.GetType(ATestClass.ClassInfo);
  618. AProperty := ARttiType.GetProperty('aInteger');
  619. i := -43573;
  620. TValue.Make(@i, TypeInfo(Integer), AValue);
  621. AProperty.SetValue(ATestClass, AValue);
  622. CheckEquals(ATestClass.AInteger, i);
  623. i := 1;
  624. CheckEquals(ATestClass.AInteger, -43573);
  625. finally
  626. AtestClass.Free;
  627. end;
  628. finally
  629. c.Free;
  630. end;
  631. end;
  632. procedure TTestRTTI.TestPropSetValueBoolean;
  633. var
  634. ATestClass : TTestValueClass;
  635. c: TRttiContext;
  636. ARttiType: TRttiType;
  637. AProperty: TRttiProperty;
  638. AValue: TValue;
  639. b: boolean;
  640. begin
  641. c := TRttiContext.Create;
  642. try
  643. ATestClass := TTestValueClass.Create;
  644. try
  645. ARttiType := c.GetType(ATestClass.ClassInfo);
  646. AProperty := ARttiType.GetProperty('aboolean');
  647. b := true;
  648. TValue.Make(@b, TypeInfo(Boolean), AValue);
  649. AProperty.SetValue(ATestClass, AValue);
  650. CheckEquals(ATestClass.ABoolean, b);
  651. b := false;
  652. CheckEquals(ATestClass.ABoolean, true);
  653. TValue.Make(@b, TypeInfo(Boolean), AValue);
  654. AProperty.SetValue(ATestClass, AValue);
  655. CheckEquals(ATestClass.ABoolean, false);
  656. finally
  657. AtestClass.Free;
  658. end;
  659. finally
  660. c.Free;
  661. end;
  662. end;
  663. procedure TTestRTTI.TestPropSetValueShortString;
  664. var
  665. ATestClass : TTestValueClass;
  666. c: TRttiContext;
  667. ARttiType: TRttiType;
  668. AProperty: TRttiProperty;
  669. AValue: TValue;
  670. s: string;
  671. ss: ShortString;
  672. begin
  673. c := TRttiContext.Create;
  674. try
  675. ATestClass := TTestValueClass.Create;
  676. try
  677. ARttiType := c.GetType(ATestClass.ClassInfo);
  678. AProperty := ARttiType.GetProperty('aShortString');
  679. s := 'ipse lorem or something like that';
  680. TValue.Make(@s, TypeInfo(String), AValue);
  681. AProperty.SetValue(ATestClass, AValue);
  682. CheckEquals(ATestClass.AShortString, s);
  683. s := 'Another string';
  684. CheckEquals(ATestClass.AShortString, 'ipse lorem or something like that');
  685. ss := 'Hello World';
  686. TValue.Make(@ss, TypeInfo(ShortString), AValue);
  687. AProperty.SetValue(ATestClass, AValue);
  688. CheckEquals(ATestClass.AShortString, ss);
  689. ss := 'Foobar';
  690. CheckEquals(ATestClass.AShortString, 'Hello World');
  691. AProperty.SetValue(ATestClass, 'Another string');
  692. CheckEquals(ATestClass.AShortString, 'Another string');
  693. finally
  694. AtestClass.Free;
  695. end;
  696. finally
  697. c.Free;
  698. end;
  699. end;
  700. procedure TTestRTTI.TestPropSetValueObject;
  701. var
  702. ATestClass : TTestValueClass;
  703. c: TRttiContext;
  704. ARttiType: TRttiType;
  705. AProperty: TRttiProperty;
  706. AValue: TValue;
  707. O: TObject;
  708. TypeInfo: PTypeInfo;
  709. begin
  710. c := TRttiContext.Create;
  711. try
  712. ATestClass := TTestValueClass.Create;
  713. try
  714. ARttiType := c.GetType(ATestClass.ClassInfo);
  715. AProperty := ARttiType.GetProperty('AObject');
  716. TypeInfo := GetPropInfo(ATestClass, 'AObject')^.PropType{$ifndef fpc}^{$endif};
  717. O := TPersistent.Create;
  718. TValue.Make(@O, TypeInfo, AValue);
  719. AProperty.SetValue(ATestClass, AValue);
  720. CheckEquals(ATestClass.AObject.GetHashCode, O.GetHashCode);
  721. O.Free;
  722. O := TPersistent.Create;
  723. AProperty.SetValue(ATestClass, O);
  724. CheckEquals(ATestClass.AObject.GetHashCode, O.GetHashCode);
  725. O.Free;
  726. finally
  727. AtestClass.Free;
  728. end;
  729. finally
  730. c.Free;
  731. end;
  732. end;
  733. procedure TTestRTTI.TestPropSetValueInterface;
  734. var
  735. ATestClass : TTestValueClass;
  736. c: TRttiContext;
  737. ARttiType: TRttiType;
  738. AProperty: TRttiProperty;
  739. AValue: TValue;
  740. TypeInfo: PTypeInfo;
  741. i: IInterface;
  742. begin
  743. c := TRttiContext.Create;
  744. try
  745. ATestClass := TTestValueClass.Create;
  746. try
  747. ARttiType := c.GetType(ATestClass.ClassInfo);
  748. AProperty := ARttiType.GetProperty('AUnknown');
  749. TypeInfo := GetPropInfo(ATestClass, 'AUnknown')^.PropType{$ifndef fpc}^{$endif};
  750. i := TInterfacedObject.Create;
  751. TValue.Make(@i, TypeInfo, AValue);
  752. AProperty.SetValue(ATestClass, AValue);
  753. Check(ATestClass.AUnknown = i);
  754. {$ifdef fpc}
  755. { Delphi does not provide an implicit assignment overload for IUnknown }
  756. i := TInterfacedObject.Create;
  757. AProperty.SetValue(ATestClass, i);
  758. Check(ATestClass.AUnknown = i);
  759. {$endif}
  760. finally
  761. AtestClass.Free;
  762. end;
  763. finally
  764. c.Free;
  765. end;
  766. end;
  767. procedure TTestRTTI.TestPropSetValueFloat;
  768. var
  769. ATestClass : TTestValueClass;
  770. c: TRttiContext;
  771. ARttiType: TRttiType;
  772. AProperty: TRttiProperty;
  773. AValue: TValue;
  774. TypeInfo: PTypeInfo;
  775. S: Single;
  776. D: Double;
  777. E: Extended;
  778. Cur: Currency;
  779. Cmp: Comp;
  780. begin
  781. c := TRttiContext.Create;
  782. try
  783. ATestClass := TTestValueClass.Create;
  784. try
  785. ARttiType := c.GetType(ATestClass.ClassInfo);
  786. AProperty := ARttiType.GetProperty('ASingle');
  787. TypeInfo := GetPropInfo(ATestClass, 'ASingle')^.PropType{$ifndef fpc}^{$endif};
  788. S := 1.1;
  789. TValue.Make(@S, TypeInfo, AValue);
  790. AProperty.SetValue(ATestClass, AValue);
  791. CheckEquals(S, ATestClass.ASingle, 0.001);
  792. S := 1.2;
  793. AProperty.SetValue(ATestClass, S);
  794. CheckEquals(S, ATestClass.ASingle, 0.001);
  795. AProperty := ARttiType.GetProperty('ADouble');
  796. TypeInfo := GetPropInfo(ATestClass, 'ADouble')^.PropType{$ifndef fpc}^{$endif};
  797. D := 2.1;
  798. TValue.Make(@D, TypeInfo, AValue);
  799. AProperty.SetValue(ATestClass, AValue);
  800. CheckEquals(D, ATestClass.ADouble, 0.001);
  801. D := 2.2;
  802. AProperty.SetValue(ATestClass, D);
  803. CheckEquals(D, ATestClass.ADouble, 0.001);
  804. AProperty := ARttiType.GetProperty('AExtended');
  805. TypeInfo := GetPropInfo(ATestClass, 'AExtended')^.PropType{$ifndef fpc}^{$endif};
  806. E := 3.1;
  807. TValue.Make(@E, TypeInfo, AValue);
  808. AProperty.SetValue(ATestClass, AValue);
  809. CheckEquals(E, ATestClass.AExtended, 0.001);
  810. E := 3.2;
  811. AProperty.SetValue(ATestClass, E);
  812. CheckEquals(E, ATestClass.AExtended, 0.001);
  813. AProperty := ARttiType.GetProperty('ACurrency');
  814. TypeInfo := GetPropInfo(ATestClass, 'ACurrency')^.PropType{$ifndef fpc}^{$endif};
  815. Cur := 40;
  816. TValue.Make(@Cur, TypeInfo, AValue);
  817. AProperty.SetValue(ATestClass, AValue);
  818. CheckEquals(Cur, ATestClass.ACurrency, 0.001);
  819. Cur := 41;
  820. AProperty.SetValue(ATestClass, Cur);
  821. CheckEquals(Cur, ATestClass.ACurrency, 0.001);
  822. AProperty := ARttiType.GetProperty('AComp');
  823. TypeInfo := GetPropInfo(ATestClass, 'AComp')^.PropType{$ifndef fpc}^{$endif};
  824. Cmp := 50;
  825. TValue.Make(@Cmp, TypeInfo, AValue);
  826. AProperty.SetValue(ATestClass, AValue);
  827. CheckEquals(Cmp, ATestClass.AComp, 0.001);
  828. Cmp := 51;
  829. AProperty.SetValue(ATestClass, Cmp);
  830. CheckEquals(Cmp, ATestClass.AComp, 0.001);
  831. finally
  832. AtestClass.Free;
  833. end;
  834. finally
  835. c.Free;
  836. end;
  837. end;
  838. procedure TTestRTTI.TestPropSetValueDynArray;
  839. var
  840. ATestClass : TTestValueClass;
  841. c: TRttiContext;
  842. ARttiType: TRttiType;
  843. AProperty: TRttiProperty;
  844. AValue: TValue;
  845. A: TTestDynArray;
  846. TypeInfo: PTypeInfo;
  847. i: Integer;
  848. begin
  849. c := TRttiContext.Create;
  850. try
  851. ATestClass := TTestValueClass.Create;
  852. try
  853. ARttiType := c.GetType(ATestClass.ClassInfo);
  854. AProperty := ARttiType.GetProperty('AArray');
  855. TypeInfo := GetPropInfo(ATestClass, 'AArray')^.PropType{$ifndef fpc}^{$endif};
  856. A := [1, 2, 3, 4, 5];
  857. TValue.Make(@A, TypeInfo, AValue);
  858. AProperty.SetValue(ATestClass, AValue);
  859. for i := 0 to High(A) do
  860. CheckEquals(A[i], ATestClass.AArray[i]);
  861. finally
  862. AtestClass.Free;
  863. end;
  864. finally
  865. c.Free;
  866. end;
  867. end;
  868. procedure TTestRTTI.TestPropSetValueEnumeration;
  869. var
  870. ATestClass : TTestValueClass;
  871. c: TRttiContext;
  872. ARttiType: TRttiType;
  873. AProperty: TRttiProperty;
  874. AValue: TValue;
  875. E: TTestEnumeration;
  876. begin
  877. c := TRttiContext.Create;
  878. try
  879. ATestClass := TTestValueClass.Create;
  880. try
  881. ARttiType := c.GetType(ATestClass.ClassInfo);
  882. AProperty := ARttiType.GetProperty('AEnumeration');
  883. E := en2;
  884. TValue.Make(@E, TypeInfo(TTestEnumeration), AValue);
  885. AProperty.SetValue(ATestClass, AValue);
  886. CheckEquals(Ord(E), Ord(ATestClass.AEnumeration));
  887. finally
  888. AtestClass.Free;
  889. end;
  890. finally
  891. c.Free;
  892. end;
  893. end;
  894. procedure TTestRTTI.TestPropSetValueChars;
  895. var
  896. ATestClass : TTestValueClass;
  897. c: TRttiContext;
  898. ARttiType: TRttiType;
  899. AProperty: TRttiProperty;
  900. AValueC, AValueW: TValue;
  901. begin
  902. c := TRttiContext.Create;
  903. try
  904. ATestClass := TTestValueClass.Create;
  905. ATestClass.AChar := 'C';
  906. ATestClass.AWideChar := 'W';
  907. try
  908. ARttiType := c.GetType(ATestClass.ClassInfo);
  909. Check(assigned(ARttiType));
  910. AProperty := ARttiType.GetProperty('AChar');
  911. AValueC := AProperty.GetValue(ATestClass);
  912. CheckEquals('C', AValueC.AsAnsiChar);
  913. AProperty := ARttiType.GetProperty('AWideChar');
  914. AValueW := AProperty.GetValue(ATestClass);
  915. CheckEquals('W', AValueW.AsWideChar);
  916. finally
  917. AtestClass.Free;
  918. end;
  919. CheckEquals('C', AValueC.AsAnsiChar);
  920. CheckEquals('W', AValueW.AsWideChar);
  921. finally
  922. c.Free;
  923. end;
  924. end;
  925. procedure TTestRTTI.TestPropGetValueProcInteger;
  926. var
  927. ATestClass : TTestValueClass;
  928. c: TRttiContext;
  929. ARttiType: TRttiType;
  930. AProperty: TRttiProperty;
  931. AValue: TValue;
  932. begin
  933. c := TRttiContext.Create;
  934. try
  935. ATestClass := TTestValueClass.Create;
  936. ATestClass.AInteger := 472349;
  937. try
  938. ARttiType := c.GetType(ATestClass.ClassInfo);
  939. Check(assigned(ARttiType));
  940. AProperty := ARttiType.GetProperty('agetinteger');
  941. AValue := AProperty.GetValue(ATestClass);
  942. CheckEquals(472349,AValue.AsInteger);
  943. finally
  944. AtestClass.Free;
  945. end;
  946. CheckEquals(472349,AValue.AsInteger);
  947. finally
  948. c.Free;
  949. end;
  950. end;
  951. procedure TTestRTTI.TestPropGetValueProcString;
  952. var
  953. ATestClass : TTestValueClass;
  954. c: TRttiContext;
  955. ARttiType: TRttiType;
  956. AProperty: TRttiProperty;
  957. AValue: TValue;
  958. begin
  959. c := TRttiContext.Create;
  960. try
  961. ATestClass := TTestValueClass.Create;
  962. ATestClass.AString := 'Hello World';
  963. try
  964. ARttiType := c.GetType(ATestClass.ClassInfo);
  965. Check(assigned(ARttiType));
  966. AProperty := ARttiType.GetProperty('agetstring');
  967. AValue := AProperty.GetValue(ATestClass);
  968. CheckEquals('Hello World',AValue.AsString);
  969. finally
  970. AtestClass.Free;
  971. end;
  972. CheckEquals('Hello World',AValue.AsString);
  973. finally
  974. c.Free;
  975. end;
  976. end;
  977. procedure TTestRTTI.TestTRttiTypeProperties;
  978. var
  979. c: TRttiContext;
  980. ARttiType: TRttiType;
  981. begin
  982. c := TRttiContext.Create;
  983. try
  984. ARttiType := c.GetType(TTestValueClass);
  985. Check(assigned(ARttiType));
  986. CheckEquals(ARttiType.Name,'TTestValueClass');
  987. Check(ARttiType.TypeKind=tkClass);
  988. // CheckEquals(ARttiType.IsPublicType,false);
  989. CheckEquals(ARttiType.TypeSize,SizeOf(TObject));
  990. CheckEquals(ARttiType.IsManaged,false);
  991. CheckEquals(ARttiType.BaseType.classname,'TRttiInstanceType');
  992. CheckEquals(ARttiType.IsInstance,True);
  993. CheckEquals(ARttiType.AsInstance.DeclaringUnitName,'tests.rtti.types');
  994. Check(ARttiType.BaseType.Name='TObject');
  995. Check(ARttiType.AsInstance.BaseType.Name='TObject');
  996. CheckEquals(ARttiType.IsOrdinal,False);
  997. CheckEquals(ARttiType.IsRecord,False);
  998. CheckEquals(ARttiType.IsSet,False);
  999. finally
  1000. c.Free;
  1001. end;
  1002. end;
  1003. procedure TTestRTTI.GetTypeInteger;
  1004. var
  1005. LContext: TRttiContext;
  1006. LType: TRttiType;
  1007. begin
  1008. LContext := TRttiContext.Create;
  1009. LType := LContext.GetType(TypeInfo(integer));
  1010. {$ifdef fpc}
  1011. CheckEquals(LType.Name, 'LongInt');
  1012. {$else}
  1013. CheckEquals(LType.Name, 'Integer');
  1014. {$endif}
  1015. LContext.Free;
  1016. end;
  1017. procedure TTestRTTI.GetTypePointer;
  1018. var
  1019. context: TRttiContext;
  1020. t: TRttiType;
  1021. p: TRttiPointerType absolute t;
  1022. begin
  1023. context := TRttiContext.Create;
  1024. try
  1025. t := context.GetType(TypeInfo(Pointer));
  1026. Assert(t is TRttiPointerType, 'Type of Pointer is not a TRttiPointerType');
  1027. Assert(not Assigned(p.ReferredType), 'ReferredType of Pointer is not Nil');
  1028. t := context.GetType(TypeInfo(PLongInt));
  1029. Assert(t is TRttiPointerType, 'Type of Pointer is not a TRttiPointerType');
  1030. Assert(Assigned(p.ReferredType), 'ReferredType of PLongInt is Nil');
  1031. Assert(p.ReferredType = context.GetType(TypeInfo(LongInt)), 'ReferredType of PLongInt is not a LongInt');
  1032. t := context.GetType(TypeInfo(PWideChar));
  1033. Assert(t is TRttiPointerType, 'Type of Pointer is not a TRttiPointerType');
  1034. Assert(Assigned(p.ReferredType), 'ReferredType of PWideChar is Nil');
  1035. Assert(p.ReferredType = context.GetType(TypeInfo(WideChar)), 'ReferredType of PWideChar is not a WideChar');
  1036. finally
  1037. context.Free;
  1038. end;
  1039. end;
  1040. procedure TTestRTTI.GetClassProperties;
  1041. var
  1042. LContext: TRttiContext;
  1043. LType: TRttiType;
  1044. PropList, PropList2: {$ifdef fpc}specialize{$endif} TArray<TRttiProperty>;
  1045. i: LongInt;
  1046. begin
  1047. LContext := TRttiContext.Create;
  1048. LType := LContext.GetType(TypeInfo(TGetClassProperties));
  1049. PropList := LType.GetProperties;
  1050. CheckEquals(4, length(PropList));
  1051. CheckEquals('PubPropRO', PropList[0].Name);
  1052. CheckEquals('PubPropRW', PropList[1].Name);
  1053. CheckEquals('PubPropSetRO', PropList[2].Name);
  1054. CheckEquals('PubPropSetRW', PropList[3].Name);
  1055. LType := LContext.GetType(TypeInfo(TGetClassPropertiesSub));
  1056. PropList2 := LType.GetProperties;
  1057. CheckEquals(Length(PropList), Length(PropList2));
  1058. for i := 0 to High(PropList) do
  1059. Check(PropList[i] = PropList2[i], 'Property instances are not equal');
  1060. LContext.Free;
  1061. end;
  1062. procedure TTestRTTI.GetClassPropertiesValue;
  1063. var
  1064. AGetClassProperties: TGetClassProperties;
  1065. LContext: TRttiContext;
  1066. LType: TRttiType;
  1067. AValue: TValue;
  1068. begin
  1069. LContext := TRttiContext.Create;
  1070. LType := LContext.GetType(TGetClassProperties);
  1071. AGetClassProperties := TGetClassProperties.Create;
  1072. try
  1073. AGetClassProperties.PubPropRW:=12345;
  1074. AValue := LType.GetProperty('PubPropRW').GetValue(AGetClassProperties);
  1075. CheckEquals(12345, AValue.AsInteger);
  1076. finally
  1077. AGetClassProperties.Free;
  1078. end;
  1079. LContext.Free;
  1080. end;
  1081. procedure TTestRTTI.TestInterface;
  1082. var
  1083. context: TRttiContext;
  1084. t: TRttiType;
  1085. ti1, ti2: TRttiInterfaceType;
  1086. methods: {$ifdef fpc}specialize{$endif} TArray<TRttiMethod>;
  1087. params: {$ifdef fpc}specialize{$endif} TArray<TRttiParameter>;
  1088. method: TRttiMethod;
  1089. param: TRttiParameter;
  1090. flag: TParamFlag;
  1091. begin
  1092. context := TRttiContext.Create;
  1093. try
  1094. t := context.GetType(TypeInfo(IInterface));
  1095. Check(t is TRttiInterfaceType, 'Type is not an interface type');
  1096. Check(not Assigned(t.BaseType), 'Base type is assigned');
  1097. ti1 := TRttiInterfaceType(t);
  1098. Check(not Assigned(ti1.BaseType), 'Base type is assigned');
  1099. methods := t.GetMethods;
  1100. CheckEquals(0, Length(methods), 'Overall method count does not match');
  1101. methods := t.GetDeclaredMethods;
  1102. CheckEquals(0, Length(methods), 'Declared method conut does not match');
  1103. t := context.GetType(TypeInfo(ITestInterface));
  1104. Check(t is TRttiInterfaceType, 'Type is not an interface type');
  1105. Check(Assigned(t.BaseType), 'Base type is not assigned');
  1106. Check(t.BaseType = TRttiType(ti1), 'Base type does not match');
  1107. ti2 := TRttiInterfaceType(t);
  1108. Check(Assigned(ti2.BaseType), 'Base type is not assigned');
  1109. Check(ti2.BaseType = ti1, 'Base type does not match');
  1110. methods := t.GetMethods;
  1111. CheckEquals(4, Length(methods), 'Overall method count does not match');
  1112. methods := t.GetDeclaredMethods;
  1113. CheckEquals(4, Length(methods), 'Declared method count does not match');
  1114. method := methods[0];
  1115. CheckEquals(method.Name, 'Test', 'Method name of Test does not match');
  1116. Check(method.CallingConvention = DefaultCC, 'Calling convention of Test does not match');
  1117. Check(method.MethodKind = mkProcedure, 'Method kind of Test does not match');
  1118. Check(method.DispatchKind = dkInterface, 'Dispatch kind of Test does not match');
  1119. Check(not Assigned(method.CodeAddress), 'Code address of Test is not Nil');
  1120. CheckEquals(method.VirtualIndex, 3, 'Virtual index of Test does not match');
  1121. Check(not Assigned(method.ReturnType), 'Return type of Test is not Nil');
  1122. params := method.GetParameters;
  1123. CheckEquals(0, Length(params), 'Parameter count of Test does not match');
  1124. method := methods[1];
  1125. CheckEquals(method.Name, 'Test2', 'Method name of Test2 does not match');
  1126. Check(method.CallingConvention = DefaultCC, 'Calling convention of Test2 does not match');
  1127. Check(method.MethodKind = mkFunction, 'Method kind of Test2 does not match');
  1128. Check(method.DispatchKind = dkInterface, 'Dispatch kind of Test2 does not match');
  1129. Check(not Assigned(method.CodeAddress), 'Code address of Test2 is not Nil');
  1130. CheckEquals(method.VirtualIndex, 4, 'Virtual index of Test2 does not match');
  1131. Check(Assigned(method.ReturnType), 'Return type of Test2 is Nil');
  1132. Check(method.ReturnType.TypeKind = tkInteger, 'Return type of Test2 is not an ordinal');
  1133. params := method.GetParameters;
  1134. CheckEquals(0, Length(params), 'Parameter count of Test2 does not match');
  1135. method := methods[2];
  1136. CheckEquals(method.Name, 'Test3', 'Method name of Test3 does not match');
  1137. Check(method.CallingConvention = DefaultCC, 'Calling convention of Test3 does not match');
  1138. Check(method.MethodKind = mkProcedure, 'Method kind of Test3 does not match');
  1139. Check(method.DispatchKind = dkInterface, 'Dispatch kind of Test3 does not match');
  1140. Check(not Assigned(method.CodeAddress), 'Code address of Test3 is not Nil');
  1141. CheckEquals(method.VirtualIndex, 5, 'Virtual index of Test3 does not match');
  1142. Check(not Assigned(method.ReturnType), 'Return type of Test3 is not Nil');
  1143. params := method.GetParameters;
  1144. CheckEquals(4, Length(params), 'Parameter count of Test3 does not match');
  1145. param := params[0];
  1146. CheckEquals(param.Name, 'aArg1', 'Parameter name of Test3.aArg1 does not match');
  1147. Check(param.Flags = [], 'Parameter flags of Test3.aArg1 do not match');
  1148. Check(Assigned(param.ParamType), 'Parameter type of Test3.aArg1 is Nil');
  1149. Check(param.ParamType.TypeKind = tkInteger, 'Parameter type of Test3.aArg1 is not an ordinal');
  1150. param := params[1];
  1151. CheckEquals(param.Name, 'aArg2', 'Parameter name of Test3.aArg2 does not match');
  1152. Check(param.Flags = [pfConst], 'Parameter flags of Test3.aArg2 do not match');
  1153. Check(Assigned(param.ParamType), 'Parameter type of Test3.aArg2 is Nil');
  1154. Check(param.ParamType.TypeKind = tkAnsiString, 'Parameter type of Test3.aArg2 is not a string');
  1155. param := params[2];
  1156. CheckEquals(param.Name, 'aArg3', 'Parameter name of Test3.aArg3 does not match');
  1157. Check(param.Flags = [pfVar], 'Parameter flags of Test3.aArg3 do not match');
  1158. Check(Assigned(param.ParamType), 'Parameter type of Test3.aArg3 is Nil');
  1159. Check(param.ParamType.TypeKind = {$ifdef fpc}tkBool{$else}tkEnumeration{$endif}, 'Parameter type of Test3.aArg3 is not a boolean');
  1160. param := params[3];
  1161. CheckEquals(param.Name, 'aArg4', 'Parameter name of Test3.aArg4 does not match');
  1162. Check(param.Flags = [pfOut], 'Parameter flags of Test3.aArg4 do not match');
  1163. Check(Assigned(param.ParamType), 'Parameter type of Test3.aArg4 is Nil');
  1164. Check(param.ParamType.TypeKind = tkInteger, 'Parameter type of Test3.aArg4 is not a string');
  1165. method := methods[3];
  1166. CheckEquals(method.Name, 'Test4', 'Method name of Test4 does not match');
  1167. Check(method.CallingConvention = DefaultCC, 'Calling convention of Test4 does not match');
  1168. Check(method.MethodKind = mkFunction, 'Method kind of Test4 does not match');
  1169. Check(method.DispatchKind = dkInterface, 'Dispatch kind of Test4 does not match');
  1170. Check(not Assigned(method.CodeAddress), 'Code address of Test4 is not Nil');
  1171. CheckEquals(method.VirtualIndex, 6, 'Virtual index of Test4 does not match');
  1172. Check(Assigned(method.ReturnType), 'Return type of Test4 is not Nil');
  1173. Check(method.ReturnType.TypeKind = tkAnsiString, 'Return type of Test4 is not a string');
  1174. params := method.GetParameters;
  1175. CheckEquals(2, Length(params), 'Parameter count of Test4 does not match');
  1176. param := params[0];
  1177. CheckEquals(param.Name, 'aArg1', 'Parameter name of Test4.aArg1 does not match');
  1178. Check(param.Flags = [pfArray, pfReference], 'Parameter flags of Test4.aArg1 do not match');
  1179. Check(Assigned(param.ParamType), 'Parameter type of Test4.aArg1 is Nil');
  1180. Check(param.ParamType.TypeKind = tkInteger, 'Parameter type of Test4.aArg1 is not an ordinal');
  1181. param := params[1];
  1182. CheckEquals(param.Name, 'aArg2', 'Parameter name of Test4.aArg2 does not match');
  1183. Check(param.Flags = [pfArray, pfReference], 'Parameter flags of Test4.aArg2 do not match');
  1184. Check(Assigned(param.ParamType), 'Parameter type of Test4.aArg2 is Nil');
  1185. Check(param.ParamType.TypeKind = tkRecord, 'Parameter type of Test4.aArg2 is not a record');
  1186. finally
  1187. context.Free;
  1188. end;
  1189. end;
  1190. procedure TTestRTTI.TestRawThunk;
  1191. var
  1192. intf: IInterface;
  1193. begin
  1194. { we test the raw thunking by instantiating a TVirtualInterface of IInterface }
  1195. { this does not require a function call manager as the thunking is implemented
  1196. directly inside the RTTI unit }
  1197. try
  1198. intf := TVirtualInterface.Create(PTypeInfo(TypeInfo(IInterface))) as IInterface;
  1199. except
  1200. on e: ENotImplemented do
  1201. Ignore('RawThunk not implemented');
  1202. end;
  1203. { if all went well QueryInterface and _AddRef were called and now we call
  1204. _Release as well }
  1205. intf := Nil;
  1206. end;
  1207. {$ifdef fpc}
  1208. procedure TTestRTTI.TestInterfaceRaw;
  1209. var
  1210. context: TRttiContext;
  1211. t: TRttiType;
  1212. ti: TRttiInterfaceType;
  1213. begin
  1214. context := TRttiContext.Create;
  1215. try
  1216. t := context.GetType(TypeInfo(ICORBATest));
  1217. Check(t is TRttiInterfaceType, 'Type is not a raw interface type');
  1218. Check(not Assigned(t.BaseType), 'Base type is assigned');
  1219. ti := TRttiInterfaceType(t);
  1220. Check(not Assigned(ti.BaseType), 'Base type is assigned');
  1221. finally
  1222. context.Free;
  1223. end;
  1224. end;
  1225. {$endif}
  1226. procedure TTestRTTI.TestArray;
  1227. var
  1228. context: TRttiContext;
  1229. t, el: TRttiType;
  1230. a: TRttiArrayType;
  1231. o: TRttiOrdinalType;
  1232. begin
  1233. context := TRttiContext.Create;
  1234. try
  1235. t := context.GetType(PTypeInfo(TypeInfo(TArrayOfLongintStatic)));
  1236. Check(t is TRttiArrayType, 'Type is not a TRttiArrayType');
  1237. a := TRttiArrayType(t);
  1238. CheckEquals(1, a.DimensionCount, 'Dimension count does not match');
  1239. CheckEquals(4, a.TotalElementCount, 'Total element count does not match');
  1240. el := a.ElementType;
  1241. Check(el is TRttiOrdinalType, 'Element type is not a TRttiOrdinalType');
  1242. Check(el = context.GetType(PTypeInfo(TypeInfo(LongInt))), 'Element type is not a LongInt');
  1243. t := a.Dimensions[0];
  1244. {$ifdef fpc}
  1245. Check(t is TRttiOrdinalType, 'Index type is not a TRttiOrdinalType');
  1246. o := TRttiOrdinalType(t);
  1247. { Currently this is a full type :/ }
  1248. {CheckEquals(0, o.MinValue, 'Minimum value of 1st dimension does not match');
  1249. CheckEquals(3, o.MaxValue, 'Maximum value of 1st dimension does not match');}
  1250. {$else}
  1251. Check(t = Nil, 'Index type is not Nil');
  1252. {$endif}
  1253. t := context.GetType(PTypeInfo(TypeInfo(TArrayOfLongint2DStatic)));
  1254. Check(t is TRttiArrayType, 'Type is not a TRttiArrayType');
  1255. a := TRttiArrayType(t);
  1256. CheckEquals(2, a.DimensionCount, 'Dimension count does not match');
  1257. CheckEquals(4 * 3, a.TotalElementCount, 'Total element count does not match');
  1258. el := a.ElementType;
  1259. Check(el is TRttiOrdinalType, 'Element type is not a TRttiOrdinalType');
  1260. Check(el = context.GetType(PTypeInfo(TypeInfo(LongInt))), 'Element type is not a LongInt');
  1261. t := a.Dimensions[0];
  1262. {$ifdef fpc}
  1263. Check(t is TRttiOrdinalType, 'Index type is not a TRttiOrdinalType');
  1264. o := TRttiOrdinalType(t);
  1265. { Currently this is a full type :/ }
  1266. {CheckEquals(0, o.MinValue, 'Minimum value of 1st dimension does not match');
  1267. CheckEquals(3, o.MaxValue, 'Maximum value of 1st dimension does not match');}
  1268. {$else}
  1269. Check(t = Nil, 'Index type is not Nil');
  1270. {$endif}
  1271. t := a.Dimensions[1];
  1272. {$ifdef fpc}
  1273. Check(t is TRttiOrdinalType, 'Index type is not a TRttiOrdinalType');
  1274. o := TRttiOrdinalType(t);
  1275. { Currently this is a full type :/ }
  1276. {CheckEquals(2, o.MinValue, 'Minimum value of 1st dimension does not match');
  1277. CheckEquals(4, o.MaxValue, 'Maximum value of 1st dimension does not match');}
  1278. {$else}
  1279. Check(t = Nil, 'Index type is not Nil');
  1280. {$endif}
  1281. finally
  1282. context.Free;
  1283. end;
  1284. end;
  1285. procedure TTestRTTI.TestDynArray;
  1286. var
  1287. context: TRttiContext;
  1288. t, el: TRttiType;
  1289. a: TRttiDynamicArrayType;
  1290. begin
  1291. context := TRttiContext.Create;
  1292. try
  1293. t := context.GetType(PTypeInfo(TypeInfo(TArrayOfLongintDyn)));
  1294. Check(t is TRttiDynamicArrayType, 'Type is not a TRttiDynamicArrayType');
  1295. a := TRttiDynamicArrayType(t);
  1296. CheckEquals('tests.rtti.types', LowerCase(a.DeclaringUnitName), 'Unit type does not match for dynamic array');
  1297. CheckEquals(a.ElementSize, SizeUInt(SizeOf(LongInt)), 'Element size does not match for dynamic array');
  1298. el := a.ElementType;
  1299. Check(el is TRttiOrdinalType, 'Element type is not a TRttiOrdinalType');
  1300. Check(el = context.GetType(PTypeInfo(TypeInfo(LongInt))), 'Element type is not a LongInt');
  1301. { ToDo: check OLE type }
  1302. finally
  1303. context.Free;
  1304. end;
  1305. end;
  1306. procedure TTestRTTI.TestProcVar;
  1307. var
  1308. context: TRttiContext;
  1309. t: TRttiType;
  1310. p: TRttiProcedureType;
  1311. params: {$ifdef fpc}specialize{$endif} TArray<TRttiParameter>;
  1312. begin
  1313. context := TRttiContext.Create;
  1314. try
  1315. t := context.GetType(PTypeInfo(TypeInfo(TTestProc)));
  1316. Check(Assigned(t), 'Rtti Type is Nil');
  1317. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1318. Check(t is TRttiProcedureType, 'Rtti Type is not a procedure type');
  1319. p := t as TRttiProcedureType;
  1320. Check(p.CallingConvention = DefaultCC, 'Calling convention does not match');
  1321. Check(not Assigned(p.ReturnType), 'Return type is assigned');
  1322. CheckEquals(0, Length(p.GetParameters), 'Procedure variable has parameters');
  1323. t := context.GetType(PTypeInfo(TypeInfo(TTestFunc1)));
  1324. Check(Assigned(t), 'Rtti Type is Nil');
  1325. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1326. Check(t is TRttiProcedureType, 'Rtti Type is not a procedure type');
  1327. p := t as TRttiProcedureType;
  1328. Check(p.CallingConvention = DefaultCC, 'Calling convention does not match');
  1329. Check(Assigned(p.ReturnType), 'Return type is not assigned');
  1330. //Check(p.ReturnType is TRttiOrdinalType, 'Return type is not an ordinal type');
  1331. CheckEquals(0, Length(p.GetParameters), 'Procedure variable has parameters');
  1332. t := context.GetType(PTypeInfo(TypeInfo(TTestFunc2)));
  1333. Check(Assigned(t), 'Rtti Type is Nil');
  1334. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1335. Check(t is TRttiProcedureType, 'Rtti Type is not a procedure type');
  1336. p := t as TRttiProcedureType;
  1337. Check(p.CallingConvention = DefaultCC, 'Calling convention does not match');
  1338. Check(Assigned(p.ReturnType), 'Return type is not assigned');
  1339. Check(p.ReturnType is TRttiStringType, 'Return type is not a string type');
  1340. params := p.GetParameters;
  1341. CheckEquals(2, Length(params), 'Procedure variable has incorrect amount of parameters');
  1342. Check(params[0].ParamType.TypeKind in [tkInteger, tkInt64], 'Parameter 1 is not an ordinal type');
  1343. //Check(params[0].ParamType is TRttiOrdinalType, 'Parameter 1 is not an ordinal type');
  1344. Check(pfArray in params[1].Flags, 'Parameter 2 is not an array');
  1345. Check(params[1].ParamType.TypeKind in [tkInteger, tkInt64], 'Parameter 2 is not an ordinal array');
  1346. finally
  1347. context.Free;
  1348. end;
  1349. end;
  1350. procedure TTestRTTI.TestMethod;
  1351. var
  1352. context: TRttiContext;
  1353. t: TRttiType;
  1354. m: TRttiMethodType;
  1355. params: {$ifdef fpc}specialize{$endif} TArray<TRttiParameter>;
  1356. begin
  1357. context := TRttiContext.Create;
  1358. try
  1359. t := context.GetType(PTypeInfo(TypeInfo(TTestMethod)));
  1360. Check(Assigned(t), 'Rtti Type is Nil');
  1361. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1362. Check(t is TRttiMethodType, 'Rtti Type is not a method type');
  1363. m := t as TRttiMethodType;
  1364. Check(m.CallingConvention = DefaultCC, 'Calling convention does not match');
  1365. Check(not Assigned(m.ReturnType), 'Return type is assigned');
  1366. CheckEquals(0, Length(m.GetParameters), 'Method variable has parameters');
  1367. t := context.GetType(PTypeInfo(TypeInfo(TTestMethod1)));
  1368. Check(Assigned(t), 'Rtti Type is Nil');
  1369. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1370. Check(t is TRttiMethodType, 'Rtti Type is not a method type');
  1371. m := t as TRttiMethodType;
  1372. Check(m.CallingConvention = DefaultCC, 'Calling convention does not match');
  1373. Check(Assigned(m.ReturnType), 'Return type is not assigned');
  1374. //Check(p.ReturnType is TRttiOrdinalType, 'Return type is not an ordinal type');
  1375. CheckEquals(0, Length(m.GetParameters), 'Method variable has parameters');
  1376. t := context.GetType(PTypeInfo(TypeInfo(TTestMethod2)));
  1377. Check(Assigned(t), 'Rtti Type is Nil');
  1378. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1379. Check(t is TRttiMethodType, 'Rtti Type is not a method type');
  1380. m := t as TRttiMethodType;
  1381. Check(m.CallingConvention = DefaultCC, 'Calling convention does not match');
  1382. Check(Assigned(m.ReturnType), 'Return type is not assigned');
  1383. Check(m.ReturnType is TRttiStringType, 'Return type is not a string type');
  1384. params := m.GetParameters;
  1385. CheckEquals(2, Length(params), 'Method variable has incorrect amount of parameters');
  1386. Check(params[0].ParamType.TypeKind in [tkInteger, tkInt64], 'Parameter 1 is not an ordinal type');
  1387. //Check(params[0].ParamType is TRttiOrdinalType, 'Parameter 1 is not an ordinal type');
  1388. Check(pfArray in params[1].Flags, 'Parameter 2 is not an array');
  1389. Check(params[1].ParamType.TypeKind in [tkInteger, tkInt64], 'Parameter 2 is not an ordinal array');
  1390. finally
  1391. context.Free;
  1392. end;
  1393. end;
  1394. initialization
  1395. {$ifdef fpc}
  1396. RegisterTest(TTestRTTI);
  1397. {$else fpc}
  1398. RegisterTest(TTestRTTI.Suite);
  1399. {$endif fpc}
  1400. end.