tests.rtti.pas 71 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305
  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. { TTestExtendedRTTI }
  68. // Note: the tests assume that TObject has no RTTI associated with it.
  69. // The tests need to be adapted so they will work in both cases.
  70. TTestExtendedRTTI = class(TTestCase)
  71. Private
  72. FCtx: TRttiContext;
  73. Procedure AssertEquals(Msg : String; aExpected,aActual : TMemberVisibility); overload;
  74. Procedure AssertEquals(Msg : String; aExpected,aActual : TTypeKind);overload;
  75. procedure CheckField(aIdx: Integer; aData: TRttiField; aName: String; aKind: TTypeKind; aVisibility: TMemberVisibility;
  76. aStrict: Boolean=False);
  77. procedure CheckMethod(aPrefix: string; aIdx: Integer; aData: TRttiMethod; aName: String; aVisibility: TMemberVisibility;
  78. aStrict: Boolean=False);
  79. procedure CheckProperty(aIdx: Integer; aData: TRttiProperty; aName: String; aKind: TTypeKind; aVisibility: TMemberVisibility;
  80. isStrict: Boolean=False);
  81. public
  82. Procedure Setup; override;
  83. Procedure TearDown; override;
  84. end;
  85. { TTestClassExtendedRTTI }
  86. TTestClassExtendedRTTI = class(TTestExtendedRtti)
  87. published
  88. Procedure TestFields;
  89. Procedure TestDeclaredFields;
  90. Procedure TestProperties;
  91. Procedure TestDeclaredMethods;
  92. Procedure TestMethods;
  93. Procedure TestMethodByAddress;
  94. Procedure TestMethodsInherited;
  95. Procedure TestPrivateFieldAttributes;
  96. Procedure TestProtectedFieldAttributes;
  97. Procedure TestPublicFieldAttributes;
  98. Procedure TestPrivatePropertyAttributes;
  99. Procedure TestProtectedPropertyAttributes;
  100. Procedure TestPublicPropertyAttributes;
  101. Procedure TestPublishedPropertyAttributes;
  102. procedure TestGetStaticProperty;
  103. procedure TestSetStaticProperty;
  104. end;
  105. { TTestRecordExtendedRTTI }
  106. TTestRecordExtendedRTTI = class(TTestExtendedRtti)
  107. published
  108. Procedure TestFields;
  109. Procedure TestProperties;
  110. Procedure TestDeclaredMethods;
  111. Procedure TestMethods;
  112. Procedure TestPrivateFieldAttributes;
  113. Procedure TestPublicFieldAttributes;
  114. end;
  115. implementation
  116. uses
  117. Tests.Rtti.Util,
  118. {tests.rtti.exttypes, }
  119. tests.rtti.attrtypes2,
  120. tests.rtti.attrtypes,
  121. tests.rtti.types;
  122. { Note: GetTypes currently only returns those types that had been acquired using
  123. GetType, so GetTypes itself can't be really tested currently }
  124. (*procedure TTestRTTI.GetTypes;
  125. var
  126. LContext: TRttiContext;
  127. LType: TRttiType;
  128. IsTestCaseClassFound: boolean;
  129. begin
  130. LContext := TRttiContext.Create;
  131. { Enumerate all types declared in the application }
  132. for LType in LContext.GetTypes() do
  133. begin
  134. if LType.Name='TTestRTTI' then
  135. IsTestCaseClassFound:=true;
  136. end;
  137. LContext.Free;
  138. CheckTrue(IsTestCaseClassFound, 'RTTI information does not contain class of testcase.');
  139. end;*)
  140. {$ifndef fpc}
  141. procedure TTestRTTI.Ignore(const aMsg: string);
  142. begin
  143. { empty }
  144. end;
  145. {$endif}
  146. procedure TTestRTTI.TestGetValueStringCastError;
  147. var
  148. ATestClass : TTestValueClass;
  149. c: TRttiContext;
  150. ARttiType: TRttiType;
  151. AValue: TValue;
  152. i: integer;
  153. HadException: boolean;
  154. begin
  155. c := TRttiContext.Create;
  156. try
  157. ATestClass := TTestValueClass.Create;
  158. ATestClass.AString := '12';
  159. try
  160. ARttiType := c.GetType(ATestClass.ClassInfo);
  161. AValue := ARttiType.GetProperty('astring').GetValue(ATestClass);
  162. HadException := false;
  163. try
  164. i := AValue.AsInteger;
  165. except
  166. on E: Exception do
  167. if E.ClassType=EInvalidCast then
  168. HadException := true;
  169. end;
  170. Check(HadException, 'No or invalid exception on invalid cast');
  171. finally
  172. AtestClass.Free;
  173. end;
  174. finally
  175. c.Free;
  176. end;
  177. end;
  178. procedure TTestRTTI.TestGetIsReadable;
  179. var
  180. c: TRttiContext;
  181. ARttiType: TRttiType;
  182. AProperty: TRttiProperty;
  183. begin
  184. c := TRttiContext.Create;
  185. try
  186. ARttiType := c.GetType(TTestValueClass);
  187. AProperty := ARttiType.GetProperty('aBoolean');
  188. CheckEquals(AProperty.IsReadable, true);
  189. AProperty := ARttiType.GetProperty('aGetBoolean');
  190. CheckEquals(AProperty.IsReadable, true);
  191. AProperty := ARttiType.GetProperty('aWriteOnly');
  192. CheckEquals(AProperty.IsReadable, False);
  193. finally
  194. c.Free;
  195. end;
  196. end;
  197. procedure TTestRTTI.TestIsWritable;
  198. var
  199. c: TRttiContext;
  200. ARttiType: TRttiType;
  201. AProperty: TRttiProperty;
  202. begin
  203. c := TRttiContext.Create;
  204. try
  205. ARttiType := c.GetType(TTestValueClass);
  206. AProperty := ARttiType.GetProperty('aBoolean');
  207. CheckEquals(AProperty.IsWritable, true);
  208. AProperty := ARttiType.GetProperty('aGetBoolean');
  209. CheckEquals(AProperty.IsWritable, false);
  210. AProperty := ARttiType.GetProperty('aWriteOnly');
  211. CheckEquals(AProperty.IsWritable, True);
  212. finally
  213. c.Free;
  214. end;
  215. end;
  216. procedure TTestRTTI.TestGetAttribute;
  217. // TMyAnnotatedClass
  218. // TMyAttribute
  219. var
  220. c: TRttiContext;
  221. aType: TRttiType;
  222. aClass : TMyAnnotatedClass;
  223. custAttr : TCustomAttribute;
  224. myAttr : TMyAttribute absolute custattr;
  225. begin
  226. aType:=nil;
  227. custAttr:=Nil;
  228. c := TRttiContext.Create;
  229. try
  230. aClass:=TMyAnnotatedClass.Create;
  231. aType := c.GetType(aClass.ClassInfo);
  232. custAttr:=aType.GetAttribute(TMyAttribute);
  233. CheckEquals(custAttr.ClassType,TMyAttribute,'Correct class');
  234. CheckEquals('something',MyAttr.value,'Correct value');
  235. finally
  236. aClass.Free;
  237. // custAttr.Free;
  238. C.Free;
  239. end;
  240. end;
  241. procedure TTestRTTI.TestPropGetValueBoolean;
  242. var
  243. ATestClass : TTestValueClass;
  244. c: TRttiContext;
  245. ARttiType: TRttiType;
  246. AProperty: TRttiProperty;
  247. AValue: TValue;
  248. begin
  249. c := TRttiContext.Create;
  250. try
  251. ATestClass := TTestValueClass.Create;
  252. ATestClass.ABoolean := true;
  253. try
  254. ARttiType := c.GetType(ATestClass.ClassInfo);
  255. Check(assigned(ARttiType));
  256. AProperty := ARttiType.GetProperty('aBoolean');
  257. AValue := AProperty.GetValue(ATestClass);
  258. CheckEquals(true,AValue.AsBoolean);
  259. ATestClass.ABoolean := false;
  260. CheckEquals(true, AValue.AsBoolean);
  261. CheckEquals('True', AValue.ToString);
  262. CheckEquals(True, AValue.IsOrdinal);
  263. CheckEquals(1, AValue.AsOrdinal);
  264. finally
  265. AtestClass.Free;
  266. end;
  267. CheckEquals(True,AValue.AsBoolean);
  268. finally
  269. c.Free;
  270. end;
  271. end;
  272. procedure TTestRTTI.TestPropGetValueShortString;
  273. var
  274. ATestClass : TTestValueClass;
  275. c: TRttiContext;
  276. ARttiType: TRttiType;
  277. AProperty: TRttiProperty;
  278. AValue: TValue;
  279. begin
  280. c := TRttiContext.Create;
  281. try
  282. ATestClass := TTestValueClass.Create;
  283. ATestClass.AShortString := 'Hello World';
  284. try
  285. ARttiType := c.GetType(ATestClass.ClassInfo);
  286. Check(assigned(ARttiType));
  287. AProperty := ARttiType.GetProperty('aShortString');
  288. AValue := AProperty.GetValue(ATestClass);
  289. CheckEquals('Hello World',AValue.AsString);
  290. ATestClass.AShortString := 'Foobar';
  291. CheckEquals('Hello World', AValue.AsString);
  292. CheckEquals(False, AValue.IsOrdinal);
  293. CheckEquals(False, AValue.IsObject);
  294. CheckEquals(False, AValue.IsArray);
  295. CheckEquals(False, AValue.IsClass);
  296. finally
  297. AtestClass.Free;
  298. end;
  299. CheckEquals('Hello World',AValue.AsString);
  300. finally
  301. c.Free;
  302. end;
  303. end;
  304. procedure TTestRTTI.TestPropGetValueInteger;
  305. var
  306. ATestClass : TTestValueClass;
  307. c: TRttiContext;
  308. ARttiType: TRttiType;
  309. AProperty: TRttiProperty;
  310. AValue: TValue;
  311. begin
  312. c := TRttiContext.Create;
  313. try
  314. ATestClass := TTestValueClass.Create;
  315. ATestClass.AInteger := 472349;
  316. try
  317. ARttiType := c.GetType(ATestClass.ClassInfo);
  318. Check(assigned(ARttiType));
  319. AProperty := ARttiType.GetProperty('ainteger');
  320. AValue := AProperty.GetValue(ATestClass);
  321. CheckEquals(472349,AValue.AsInteger);
  322. ATestClass.AInteger := 12;
  323. CheckEquals(472349, AValue.AsInteger);
  324. CheckEquals('472349', AValue.ToString);
  325. CheckEquals(True, AValue.IsOrdinal);
  326. finally
  327. AtestClass.Free;
  328. end;
  329. CheckEquals(472349,AValue.AsInteger);
  330. finally
  331. c.Free;
  332. end;
  333. end;
  334. procedure TTestRTTI.TestPropGetValueString;
  335. var
  336. ATestClass : TTestValueClass;
  337. c: TRttiContext;
  338. ARttiType: TRttiType;
  339. AProperty: TRttiProperty;
  340. AValue: TValue;
  341. i: int64;
  342. begin
  343. c := TRttiContext.Create;
  344. try
  345. ATestClass := TTestValueClass.Create;
  346. ATestClass.AString := 'Hello World';
  347. try
  348. ARttiType := c.GetType(ATestClass.ClassInfo);
  349. Check(assigned(ARttiType));
  350. AProperty := ARttiType.GetProperty('astring');
  351. AValue := AProperty.GetValue(ATestClass);
  352. CheckEquals('Hello World',AValue.AsString);
  353. ATestClass.AString := 'Goodbye World';
  354. CheckEquals('Hello World',AValue.AsString);
  355. CheckEquals('Hello World',AValue.ToString);
  356. Check(TypeInfo(string)=AValue.TypeInfo);
  357. Check(AValue.TypeData=GetTypeData(AValue.TypeInfo));
  358. Check(AValue.IsEmpty=false);
  359. Check(AValue.IsObject=false);
  360. Check(AValue.IsClass=false);
  361. CheckEquals(AValue.IsOrdinal, false);
  362. CheckEquals(AValue.TryAsOrdinal(i), false);
  363. CheckEquals(AValue.IsType(TypeInfo(string)), true);
  364. CheckEquals(AValue.IsType(TypeInfo(integer)), false);
  365. CheckEquals(AValue.IsArray, false);
  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.TestPropGetValueProcBoolean;
  375. var
  376. ATestClass : TTestValueClass;
  377. c: TRttiContext;
  378. ARttiType: TRttiType;
  379. AProperty: TRttiProperty;
  380. AValue: TValue;
  381. begin
  382. c := TRttiContext.Create;
  383. try
  384. ATestClass := TTestValueClass.Create;
  385. ATestClass.ABoolean := true;
  386. try
  387. ARttiType := c.GetType(ATestClass.ClassInfo);
  388. Check(assigned(ARttiType));
  389. AProperty := ARttiType.GetProperty('aGetBoolean');
  390. AValue := AProperty.GetValue(ATestClass);
  391. CheckEquals(true,AValue.AsBoolean);
  392. finally
  393. AtestClass.Free;
  394. end;
  395. CheckEquals(True,AValue.AsBoolean);
  396. finally
  397. c.Free;
  398. end;
  399. end;
  400. procedure TTestRTTI.TestPropGetValueProcShortString;
  401. var
  402. ATestClass : TTestValueClass;
  403. c: TRttiContext;
  404. ARttiType: TRttiType;
  405. AProperty: TRttiProperty;
  406. AValue: TValue;
  407. begin
  408. c := TRttiContext.Create;
  409. try
  410. ATestClass := TTestValueClass.Create;
  411. ATestClass.AShortString := 'Hello World';
  412. try
  413. ARttiType := c.GetType(ATestClass.ClassInfo);
  414. Check(assigned(ARttiType));
  415. AProperty := ARttiType.GetProperty('aGetShortString');
  416. AValue := AProperty.GetValue(ATestClass);
  417. CheckEquals('Hello World',AValue.AsString);
  418. finally
  419. AtestClass.Free;
  420. end;
  421. CheckEquals('Hello World',AValue.AsString);
  422. finally
  423. c.Free;
  424. end;
  425. end;
  426. procedure TTestRTTI.TestPropGetValueObject;
  427. var
  428. ATestClass : TTestValueClass;
  429. c: TRttiContext;
  430. ARttiType: TRttiType;
  431. AProperty: TRttiProperty;
  432. AValue: TValue;
  433. O: TObject;
  434. begin
  435. c := TRttiContext.Create;
  436. O := TObject.Create;
  437. try
  438. ATestClass := TTestValueClass.Create;
  439. ATestClass.AObject := O;
  440. try
  441. ARttiType := c.GetType(ATestClass.ClassInfo);
  442. Check(assigned(ARttiType));
  443. AProperty := ARttiType.GetProperty('AObject');
  444. AValue := AProperty.GetValue(ATestClass);
  445. CheckEquals(O.GetHashCode, AValue.AsObject.GetHashCode);
  446. finally
  447. AtestClass.Free;
  448. end;
  449. CheckEquals(O.GetHashCode, AValue.AsObject.GetHashCode);
  450. finally
  451. c.Free;
  452. O.Free;
  453. end;
  454. end;
  455. procedure TTestRTTI.TestPropGetValueInterface;
  456. var
  457. ATestClass : TTestValueClass;
  458. c: TRttiContext;
  459. ARttiType: TRttiType;
  460. AProperty: TRttiProperty;
  461. AValue: TValue;
  462. i: IInterface;
  463. begin
  464. c := TRttiContext.Create;
  465. i := TInterfacedObject.Create;
  466. try
  467. ATestClass := TTestValueClass.Create;
  468. ATestClass.AUnknown := i;
  469. try
  470. ARttiType := c.GetType(ATestClass.ClassInfo);
  471. Check(assigned(ARttiType));
  472. AProperty := ARttiType.GetProperty('AUnknown');
  473. AValue := AProperty.GetValue(ATestClass);
  474. Check(i = AValue.AsInterface);
  475. finally
  476. AtestClass.Free;
  477. end;
  478. Check(i = AValue.AsInterface);
  479. finally
  480. c.Free;
  481. end;
  482. end;
  483. procedure TTestRTTI.TestPropGetValueFloat;
  484. var
  485. ATestClass : TTestValueClass;
  486. c: TRttiContext;
  487. ARttiType: TRttiType;
  488. AProperty: TRttiProperty;
  489. AValueS, AValueD, AValueE, AValueC, AValueCm: TValue;
  490. begin
  491. c := TRttiContext.Create;
  492. try
  493. ATestClass := TTestValueClass.Create;
  494. ATestClass.ASingle := 1.1;
  495. ATestClass.ADouble := 2.2;
  496. ATestClass.AExtended := 3.3;
  497. ATestClass.ACurrency := 4;
  498. ATestClass.AComp := 5;
  499. try
  500. ARttiType := c.GetType(ATestClass.ClassInfo);
  501. Check(assigned(ARttiType));
  502. AProperty := ARttiType.GetProperty('ASingle');
  503. AValueS := AProperty.GetValue(ATestClass);
  504. CheckEquals(1.1, AValueS.AsExtended, 0.001);
  505. AProperty := ARttiType.GetProperty('ADouble');
  506. AValueD := AProperty.GetValue(ATestClass);
  507. CheckEquals(2.2, AValueD.AsExtended, 0.001);
  508. AProperty := ARttiType.GetProperty('AExtended');
  509. AValueE := AProperty.GetValue(ATestClass);
  510. CheckEquals(3.3, AValueE.AsExtended, 0.001);
  511. AProperty := ARttiType.GetProperty('ACurrency');
  512. AValueC := AProperty.GetValue(ATestClass);
  513. CheckEquals(4.0, AValueC.AsExtended, 0.001);
  514. AProperty := ARttiType.GetProperty('AComp');
  515. AValueCm := AProperty.GetValue(ATestClass);
  516. CheckEquals(5.0, AValueCm.AsExtended, 0.001);
  517. finally
  518. AtestClass.Free;
  519. end;
  520. CheckEquals(1.1, AValueS.AsExtended, 0.001);
  521. CheckEquals(2.2, AValueD.AsExtended, 0.001);
  522. CheckEquals(3.3, AValueE.AsExtended, 0.001);
  523. CheckEquals(4.0, AValueC.AsExtended, 0.001);
  524. CheckEquals(5.0, AValueCm.AsExtended, 0.001);
  525. finally
  526. c.Free;
  527. end;
  528. end;
  529. procedure TTestRTTI.TestPropGetValueDynArray;
  530. var
  531. ATestClass : TTestValueClass;
  532. c: TRttiContext;
  533. ARttiType: TRttiType;
  534. AProperty: TRttiProperty;
  535. AValue: TValue;
  536. A: TTestDynArray;
  537. begin
  538. c := TRttiContext.Create;
  539. A := [1, 2, 3, 4];
  540. try
  541. ATestClass := TTestValueClass.Create;
  542. ATestClass.AArray := A;
  543. try
  544. ARttiType := c.GetType(ATestClass.ClassInfo);
  545. Check(assigned(ARttiType));
  546. AProperty := ARttiType.GetProperty('AArray');
  547. AValue := AProperty.GetValue(ATestClass);
  548. CheckEquals(A[0], AValue.GetArrayElement(0).AsInteger);
  549. CheckEquals(A[1], AValue.GetArrayElement(1).AsInteger);
  550. CheckEquals(A[2], AValue.GetArrayElement(2).AsInteger);
  551. CheckEquals(A[3], AValue.GetArrayElement(3).AsInteger);
  552. finally
  553. AtestClass.Free;
  554. end;
  555. finally
  556. c.Free;
  557. end;
  558. end;
  559. procedure TTestRTTI.TestPropGetValueEnumeration;
  560. var
  561. ATestClass : TTestValueClass;
  562. c: TRttiContext;
  563. ARttiType: TRttiType;
  564. AProperty: TRttiProperty;
  565. AValue: TValue;
  566. begin
  567. c := TRttiContext.Create;
  568. try
  569. ATestClass := TTestValueClass.Create;
  570. ATestClass.AEnumeration := en3;
  571. try
  572. ARttiType := c.GetType(ATestClass.ClassInfo);
  573. Check(assigned(ARttiType));
  574. AProperty := ARttiType.GetProperty('AEnumeration');
  575. AValue := AProperty.GetValue(ATestClass);
  576. CheckEquals(Ord(en3),AValue.AsOrdinal);
  577. ATestClass.AEnumeration := en1;
  578. CheckEquals(Ord(en3), AValue.AsOrdinal);
  579. CheckEquals('en3', AValue.ToString);
  580. CheckEquals(True, AValue.IsOrdinal);
  581. finally
  582. AtestClass.Free;
  583. end;
  584. CheckEquals(Ord(en3),AValue.AsOrdinal);
  585. finally
  586. c.Free;
  587. end;
  588. end;
  589. procedure TTestRTTI.TestPropGetValueChars;
  590. var
  591. ATestClass : TTestValueClass;
  592. c: TRttiContext;
  593. ARttiType: TRttiType;
  594. AProperty: TRttiProperty;
  595. AValueC, AValueW: TValue;
  596. begin
  597. c := TRttiContext.Create;
  598. try
  599. ATestClass := TTestValueClass.Create;
  600. ATestClass.AChar := 'C';
  601. ATestClass.AWideChar := 'W';
  602. try
  603. ARttiType := c.GetType(ATestClass.ClassInfo);
  604. Check(assigned(ARttiType));
  605. AProperty := ARttiType.GetProperty('AChar');
  606. AValueC := AProperty.GetValue(ATestClass);
  607. CheckEquals('C',AValueC.AsAnsiChar);
  608. ATestClass.AChar := 'N';
  609. CheckEquals('C', AValueC.AsAnsiChar);
  610. CheckEquals('C', AValueC.ToString);
  611. CheckEquals(True, AValueC.IsOrdinal);
  612. AProperty := ARttiType.GetProperty('AWideChar');
  613. AValueW := AProperty.GetValue(ATestClass);
  614. CheckEquals('W',AValueW.AsWideChar);
  615. ATestClass.AWideChar := 'Z';
  616. CheckEquals('W', AValueW.AsWideChar);
  617. CheckEquals('W', AValueW.ToString);
  618. CheckEquals(True, AValueW.IsOrdinal);
  619. finally
  620. AtestClass.Free;
  621. end;
  622. CheckEquals('C',AValueC.AsAnsiChar);
  623. CheckEquals('W',AValueW.AsWideChar);
  624. finally
  625. c.Free;
  626. end;
  627. end;
  628. procedure TTestRTTI.TestPropSetValueString;
  629. var
  630. ATestClass : TTestValueClass;
  631. c: TRttiContext;
  632. ARttiType: TRttiType;
  633. AProperty: TRttiProperty;
  634. AValue: TValue;
  635. s: string;
  636. begin
  637. c := TRttiContext.Create;
  638. try
  639. ATestClass := TTestValueClass.Create;
  640. try
  641. ARttiType := c.GetType(ATestClass.ClassInfo);
  642. AProperty := ARttiType.GetProperty('astring');
  643. s := 'ipse lorem or something like that';
  644. TValue.Make(@s, TypeInfo(string), AValue);
  645. AProperty.SetValue(ATestClass, AValue);
  646. CheckEquals(ATestClass.AString, s);
  647. s := 'Another string';
  648. CheckEquals(ATestClass.AString, 'ipse lorem or something like that');
  649. finally
  650. AtestClass.Free;
  651. end;
  652. finally
  653. c.Free;
  654. end;
  655. end;
  656. procedure TTestRTTI.TestPropSetValueInteger;
  657. var
  658. ATestClass : TTestValueClass;
  659. c: TRttiContext;
  660. ARttiType: TRttiType;
  661. AProperty: TRttiProperty;
  662. AValue: TValue;
  663. i: integer;
  664. begin
  665. c := TRttiContext.Create;
  666. try
  667. ATestClass := TTestValueClass.Create;
  668. try
  669. ARttiType := c.GetType(ATestClass.ClassInfo);
  670. AProperty := ARttiType.GetProperty('aInteger');
  671. i := -43573;
  672. TValue.Make(@i, TypeInfo(Integer), AValue);
  673. AProperty.SetValue(ATestClass, AValue);
  674. CheckEquals(ATestClass.AInteger, i);
  675. i := 1;
  676. CheckEquals(ATestClass.AInteger, -43573);
  677. finally
  678. AtestClass.Free;
  679. end;
  680. finally
  681. c.Free;
  682. end;
  683. end;
  684. procedure TTestRTTI.TestPropSetValueBoolean;
  685. var
  686. ATestClass : TTestValueClass;
  687. c: TRttiContext;
  688. ARttiType: TRttiType;
  689. AProperty: TRttiProperty;
  690. AValue: TValue;
  691. b: boolean;
  692. begin
  693. c := TRttiContext.Create;
  694. try
  695. ATestClass := TTestValueClass.Create;
  696. try
  697. ARttiType := c.GetType(ATestClass.ClassInfo);
  698. AProperty := ARttiType.GetProperty('aboolean');
  699. b := true;
  700. TValue.Make(@b, TypeInfo(Boolean), AValue);
  701. AProperty.SetValue(ATestClass, AValue);
  702. CheckEquals(ATestClass.ABoolean, b);
  703. b := false;
  704. CheckEquals(ATestClass.ABoolean, true);
  705. TValue.Make(@b, TypeInfo(Boolean), AValue);
  706. AProperty.SetValue(ATestClass, AValue);
  707. CheckEquals(ATestClass.ABoolean, false);
  708. finally
  709. AtestClass.Free;
  710. end;
  711. finally
  712. c.Free;
  713. end;
  714. end;
  715. procedure TTestRTTI.TestPropSetValueShortString;
  716. var
  717. ATestClass : TTestValueClass;
  718. c: TRttiContext;
  719. ARttiType: TRttiType;
  720. AProperty: TRttiProperty;
  721. AValue: TValue;
  722. s: string;
  723. ss: ShortString;
  724. begin
  725. c := TRttiContext.Create;
  726. try
  727. ATestClass := TTestValueClass.Create;
  728. try
  729. ARttiType := c.GetType(ATestClass.ClassInfo);
  730. AProperty := ARttiType.GetProperty('aShortString');
  731. s := 'ipse lorem or something like that';
  732. TValue.Make(@s, TypeInfo(String), AValue);
  733. AProperty.SetValue(ATestClass, AValue);
  734. CheckEquals(ATestClass.AShortString, s);
  735. s := 'Another string';
  736. CheckEquals(ATestClass.AShortString, 'ipse lorem or something like that');
  737. ss := 'Hello World';
  738. TValue.Make(@ss, TypeInfo(ShortString), AValue);
  739. AProperty.SetValue(ATestClass, AValue);
  740. CheckEquals(ATestClass.AShortString, ss);
  741. ss := 'Foobar';
  742. CheckEquals(ATestClass.AShortString, 'Hello World');
  743. AProperty.SetValue(ATestClass, 'Another string');
  744. CheckEquals(ATestClass.AShortString, 'Another string');
  745. finally
  746. AtestClass.Free;
  747. end;
  748. finally
  749. c.Free;
  750. end;
  751. end;
  752. procedure TTestRTTI.TestPropSetValueObject;
  753. var
  754. ATestClass : TTestValueClass;
  755. c: TRttiContext;
  756. ARttiType: TRttiType;
  757. AProperty: TRttiProperty;
  758. AValue: TValue;
  759. O: TObject;
  760. TypeInfo: PTypeInfo;
  761. begin
  762. c := TRttiContext.Create;
  763. try
  764. ATestClass := TTestValueClass.Create;
  765. try
  766. ARttiType := c.GetType(ATestClass.ClassInfo);
  767. AProperty := ARttiType.GetProperty('AObject');
  768. TypeInfo := GetPropInfo(ATestClass, 'AObject')^.PropType{$ifndef fpc}^{$endif};
  769. O := TPersistent.Create;
  770. TValue.Make(@O, TypeInfo, AValue);
  771. AProperty.SetValue(ATestClass, AValue);
  772. CheckEquals(ATestClass.AObject.GetHashCode, O.GetHashCode);
  773. O.Free;
  774. O := TPersistent.Create;
  775. AProperty.SetValue(ATestClass, O);
  776. CheckEquals(ATestClass.AObject.GetHashCode, O.GetHashCode);
  777. O.Free;
  778. finally
  779. AtestClass.Free;
  780. end;
  781. finally
  782. c.Free;
  783. end;
  784. end;
  785. procedure TTestRTTI.TestPropSetValueInterface;
  786. var
  787. ATestClass : TTestValueClass;
  788. c: TRttiContext;
  789. ARttiType: TRttiType;
  790. AProperty: TRttiProperty;
  791. AValue: TValue;
  792. TypeInfo: PTypeInfo;
  793. i: IInterface;
  794. begin
  795. c := TRttiContext.Create;
  796. try
  797. ATestClass := TTestValueClass.Create;
  798. try
  799. ARttiType := c.GetType(ATestClass.ClassInfo);
  800. AProperty := ARttiType.GetProperty('AUnknown');
  801. TypeInfo := GetPropInfo(ATestClass, 'AUnknown')^.PropType{$ifndef fpc}^{$endif};
  802. i := TInterfacedObject.Create;
  803. TValue.Make(@i, TypeInfo, AValue);
  804. AProperty.SetValue(ATestClass, AValue);
  805. Check(ATestClass.AUnknown = i);
  806. {$ifdef fpc}
  807. { Delphi does not provide an implicit assignment overload for IUnknown }
  808. i := TInterfacedObject.Create;
  809. AProperty.SetValue(ATestClass, i);
  810. Check(ATestClass.AUnknown = i);
  811. {$endif}
  812. finally
  813. AtestClass.Free;
  814. end;
  815. finally
  816. c.Free;
  817. end;
  818. end;
  819. procedure TTestRTTI.TestPropSetValueFloat;
  820. var
  821. ATestClass : TTestValueClass;
  822. c: TRttiContext;
  823. ARttiType: TRttiType;
  824. AProperty: TRttiProperty;
  825. AValue: TValue;
  826. TypeInfo: PTypeInfo;
  827. S: Single;
  828. D: Double;
  829. E: Extended;
  830. Cur: Currency;
  831. Cmp: Comp;
  832. begin
  833. c := TRttiContext.Create;
  834. try
  835. ATestClass := TTestValueClass.Create;
  836. try
  837. ARttiType := c.GetType(ATestClass.ClassInfo);
  838. AProperty := ARttiType.GetProperty('ASingle');
  839. TypeInfo := GetPropInfo(ATestClass, 'ASingle')^.PropType{$ifndef fpc}^{$endif};
  840. S := 1.1;
  841. TValue.Make(@S, TypeInfo, AValue);
  842. AProperty.SetValue(ATestClass, AValue);
  843. CheckEquals(S, ATestClass.ASingle, 0.001);
  844. S := 1.2;
  845. AProperty.SetValue(ATestClass, S);
  846. CheckEquals(S, ATestClass.ASingle, 0.001);
  847. AProperty := ARttiType.GetProperty('ADouble');
  848. TypeInfo := GetPropInfo(ATestClass, 'ADouble')^.PropType{$ifndef fpc}^{$endif};
  849. D := 2.1;
  850. TValue.Make(@D, TypeInfo, AValue);
  851. AProperty.SetValue(ATestClass, AValue);
  852. CheckEquals(D, ATestClass.ADouble, 0.001);
  853. D := 2.2;
  854. AProperty.SetValue(ATestClass, D);
  855. CheckEquals(D, ATestClass.ADouble, 0.001);
  856. AProperty := ARttiType.GetProperty('AExtended');
  857. TypeInfo := GetPropInfo(ATestClass, 'AExtended')^.PropType{$ifndef fpc}^{$endif};
  858. E := 3.1;
  859. TValue.Make(@E, TypeInfo, AValue);
  860. AProperty.SetValue(ATestClass, AValue);
  861. CheckEquals(E, ATestClass.AExtended, 0.001);
  862. E := 3.2;
  863. AProperty.SetValue(ATestClass, E);
  864. CheckEquals(E, ATestClass.AExtended, 0.001);
  865. AProperty := ARttiType.GetProperty('ACurrency');
  866. TypeInfo := GetPropInfo(ATestClass, 'ACurrency')^.PropType{$ifndef fpc}^{$endif};
  867. Cur := 40;
  868. TValue.Make(@Cur, TypeInfo, AValue);
  869. AProperty.SetValue(ATestClass, AValue);
  870. CheckEquals(Cur, ATestClass.ACurrency, 0.001);
  871. Cur := 41;
  872. AProperty.SetValue(ATestClass, Cur);
  873. CheckEquals(Cur, ATestClass.ACurrency, 0.001);
  874. AProperty := ARttiType.GetProperty('AComp');
  875. TypeInfo := GetPropInfo(ATestClass, 'AComp')^.PropType{$ifndef fpc}^{$endif};
  876. Cmp := 50;
  877. TValue.Make(@Cmp, TypeInfo, AValue);
  878. AProperty.SetValue(ATestClass, AValue);
  879. CheckEquals(Cmp, ATestClass.AComp, 0.001);
  880. Cmp := 51;
  881. AProperty.SetValue(ATestClass, Cmp);
  882. CheckEquals(Cmp, ATestClass.AComp, 0.001);
  883. finally
  884. AtestClass.Free;
  885. end;
  886. finally
  887. c.Free;
  888. end;
  889. end;
  890. procedure TTestRTTI.TestPropSetValueDynArray;
  891. var
  892. ATestClass : TTestValueClass;
  893. c: TRttiContext;
  894. ARttiType: TRttiType;
  895. AProperty: TRttiProperty;
  896. AValue: TValue;
  897. A: TTestDynArray;
  898. TypeInfo: PTypeInfo;
  899. i: Integer;
  900. begin
  901. c := TRttiContext.Create;
  902. try
  903. ATestClass := TTestValueClass.Create;
  904. try
  905. ARttiType := c.GetType(ATestClass.ClassInfo);
  906. AProperty := ARttiType.GetProperty('AArray');
  907. TypeInfo := GetPropInfo(ATestClass, 'AArray')^.PropType{$ifndef fpc}^{$endif};
  908. A := [1, 2, 3, 4, 5];
  909. TValue.Make(@A, TypeInfo, AValue);
  910. AProperty.SetValue(ATestClass, AValue);
  911. for i := 0 to High(A) do
  912. CheckEquals(A[i], ATestClass.AArray[i]);
  913. finally
  914. AtestClass.Free;
  915. end;
  916. finally
  917. c.Free;
  918. end;
  919. end;
  920. procedure TTestRTTI.TestPropSetValueEnumeration;
  921. var
  922. ATestClass : TTestValueClass;
  923. c: TRttiContext;
  924. ARttiType: TRttiType;
  925. AProperty: TRttiProperty;
  926. AValue: TValue;
  927. E: TTestEnumeration;
  928. begin
  929. c := TRttiContext.Create;
  930. try
  931. ATestClass := TTestValueClass.Create;
  932. try
  933. ARttiType := c.GetType(ATestClass.ClassInfo);
  934. AProperty := ARttiType.GetProperty('AEnumeration');
  935. E := en2;
  936. TValue.Make(@E, TypeInfo(TTestEnumeration), AValue);
  937. AProperty.SetValue(ATestClass, AValue);
  938. CheckEquals(Ord(E), Ord(ATestClass.AEnumeration));
  939. finally
  940. AtestClass.Free;
  941. end;
  942. finally
  943. c.Free;
  944. end;
  945. end;
  946. procedure TTestRTTI.TestPropSetValueChars;
  947. var
  948. ATestClass : TTestValueClass;
  949. c: TRttiContext;
  950. ARttiType: TRttiType;
  951. AProperty: TRttiProperty;
  952. AValueC, AValueW: TValue;
  953. begin
  954. c := TRttiContext.Create;
  955. try
  956. ATestClass := TTestValueClass.Create;
  957. ATestClass.AChar := 'C';
  958. ATestClass.AWideChar := 'W';
  959. try
  960. ARttiType := c.GetType(ATestClass.ClassInfo);
  961. Check(assigned(ARttiType));
  962. AProperty := ARttiType.GetProperty('AChar');
  963. AValueC := AProperty.GetValue(ATestClass);
  964. CheckEquals('C', AValueC.AsAnsiChar);
  965. AProperty := ARttiType.GetProperty('AWideChar');
  966. AValueW := AProperty.GetValue(ATestClass);
  967. CheckEquals('W', AValueW.AsWideChar);
  968. finally
  969. AtestClass.Free;
  970. end;
  971. CheckEquals('C', AValueC.AsAnsiChar);
  972. CheckEquals('W', AValueW.AsWideChar);
  973. finally
  974. c.Free;
  975. end;
  976. end;
  977. procedure TTestRTTI.TestPropGetValueProcInteger;
  978. var
  979. ATestClass : TTestValueClass;
  980. c: TRttiContext;
  981. ARttiType: TRttiType;
  982. AProperty: TRttiProperty;
  983. AValue: TValue;
  984. begin
  985. c := TRttiContext.Create;
  986. try
  987. ATestClass := TTestValueClass.Create;
  988. ATestClass.AInteger := 472349;
  989. try
  990. ARttiType := c.GetType(ATestClass.ClassInfo);
  991. Check(assigned(ARttiType));
  992. AProperty := ARttiType.GetProperty('agetinteger');
  993. AValue := AProperty.GetValue(ATestClass);
  994. CheckEquals(472349,AValue.AsInteger);
  995. finally
  996. AtestClass.Free;
  997. end;
  998. CheckEquals(472349,AValue.AsInteger);
  999. finally
  1000. c.Free;
  1001. end;
  1002. end;
  1003. procedure TTestRTTI.TestPropGetValueProcString;
  1004. var
  1005. ATestClass : TTestValueClass;
  1006. c: TRttiContext;
  1007. ARttiType: TRttiType;
  1008. AProperty: TRttiProperty;
  1009. AValue: TValue;
  1010. begin
  1011. c := TRttiContext.Create;
  1012. try
  1013. ATestClass := TTestValueClass.Create;
  1014. ATestClass.AString := 'Hello World';
  1015. try
  1016. ARttiType := c.GetType(ATestClass.ClassInfo);
  1017. Check(assigned(ARttiType));
  1018. AProperty := ARttiType.GetProperty('agetstring');
  1019. AValue := AProperty.GetValue(ATestClass);
  1020. CheckEquals('Hello World',AValue.AsString);
  1021. finally
  1022. AtestClass.Free;
  1023. end;
  1024. CheckEquals('Hello World',AValue.AsString);
  1025. finally
  1026. c.Free;
  1027. end;
  1028. end;
  1029. procedure TTestRTTI.TestTRttiTypeProperties;
  1030. var
  1031. c: TRttiContext;
  1032. ARttiType: TRttiType;
  1033. begin
  1034. c := TRttiContext.Create;
  1035. try
  1036. ARttiType := c.GetType(TTestValueClass);
  1037. Check(assigned(ARttiType));
  1038. CheckEquals(ARttiType.Name,'TTestValueClass');
  1039. Check(ARttiType.TypeKind=tkClass);
  1040. // CheckEquals(ARttiType.IsPublicType,false);
  1041. CheckEquals(ARttiType.TypeSize,SizeOf(TObject));
  1042. CheckEquals(ARttiType.IsManaged,false);
  1043. CheckEquals(ARttiType.BaseType.classname,'TRttiInstanceType');
  1044. CheckEquals(ARttiType.IsInstance,True);
  1045. CheckEquals(ARttiType.AsInstance.DeclaringUnitName,'tests.rtti.types');
  1046. Check(ARttiType.BaseType.Name='TObject');
  1047. Check(ARttiType.AsInstance.BaseType.Name='TObject');
  1048. CheckEquals(ARttiType.IsOrdinal,False);
  1049. CheckEquals(ARttiType.IsRecord,False);
  1050. CheckEquals(ARttiType.IsSet,False);
  1051. finally
  1052. c.Free;
  1053. end;
  1054. end;
  1055. procedure TTestRTTI.GetTypeInteger;
  1056. var
  1057. LContext: TRttiContext;
  1058. LType: TRttiType;
  1059. begin
  1060. LContext := TRttiContext.Create;
  1061. LType := LContext.GetType(TypeInfo(integer));
  1062. {$ifdef fpc}
  1063. CheckEquals(LType.Name, 'LongInt');
  1064. {$else}
  1065. CheckEquals(LType.Name, 'Integer');
  1066. {$endif}
  1067. LContext.Free;
  1068. end;
  1069. procedure TTestRTTI.GetTypePointer;
  1070. var
  1071. context: TRttiContext;
  1072. t: TRttiType;
  1073. p: TRttiPointerType absolute t;
  1074. begin
  1075. context := TRttiContext.Create;
  1076. try
  1077. t := context.GetType(TypeInfo(Pointer));
  1078. Assert(t is TRttiPointerType, 'Type of Pointer is not a TRttiPointerType');
  1079. Assert(not Assigned(p.ReferredType), 'ReferredType of Pointer is not Nil');
  1080. t := context.GetType(TypeInfo(PLongInt));
  1081. Assert(t is TRttiPointerType, 'Type of Pointer is not a TRttiPointerType');
  1082. Assert(Assigned(p.ReferredType), 'ReferredType of PLongInt is Nil');
  1083. Assert(p.ReferredType = context.GetType(TypeInfo(LongInt)), 'ReferredType of PLongInt is not a LongInt');
  1084. t := context.GetType(TypeInfo(PWideChar));
  1085. Assert(t is TRttiPointerType, 'Type of Pointer is not a TRttiPointerType');
  1086. Assert(Assigned(p.ReferredType), 'ReferredType of PWideChar is Nil');
  1087. Assert(p.ReferredType = context.GetType(TypeInfo(WideChar)), 'ReferredType of PWideChar is not a WideChar');
  1088. finally
  1089. context.Free;
  1090. end;
  1091. end;
  1092. procedure TTestRTTI.GetClassProperties;
  1093. var
  1094. LContext: TRttiContext;
  1095. LType: TRttiType;
  1096. PropList, PropList2: {$ifdef fpc}specialize{$endif} TArray<TRttiProperty>;
  1097. i: LongInt;
  1098. begin
  1099. LContext := TRttiContext.Create;
  1100. LType := LContext.GetType(TypeInfo(TGetClassProperties));
  1101. PropList := LType.GetProperties;
  1102. CheckEquals(4, length(PropList));
  1103. CheckEquals('PubPropRO', PropList[0].Name);
  1104. CheckEquals('PubPropRW', PropList[1].Name);
  1105. CheckEquals('PubPropSetRO', PropList[2].Name);
  1106. CheckEquals('PubPropSetRW', PropList[3].Name);
  1107. LType := LContext.GetType(TypeInfo(TGetClassPropertiesSub));
  1108. PropList2 := LType.GetProperties;
  1109. CheckEquals(Length(PropList), Length(PropList2));
  1110. for i := 0 to High(PropList) do
  1111. Check(PropList[i] = PropList2[i], 'Property instances are not equal');
  1112. LContext.Free;
  1113. end;
  1114. procedure TTestRTTI.GetClassPropertiesValue;
  1115. var
  1116. AGetClassProperties: TGetClassProperties;
  1117. LContext: TRttiContext;
  1118. LType: TRttiType;
  1119. AValue: TValue;
  1120. begin
  1121. LContext := TRttiContext.Create;
  1122. LType := LContext.GetType(TGetClassProperties);
  1123. AGetClassProperties := TGetClassProperties.Create;
  1124. try
  1125. AGetClassProperties.PubPropRW:=12345;
  1126. AValue := LType.GetProperty('PubPropRW').GetValue(AGetClassProperties);
  1127. CheckEquals(12345, AValue.AsInteger);
  1128. finally
  1129. AGetClassProperties.Free;
  1130. end;
  1131. LContext.Free;
  1132. end;
  1133. procedure TTestRTTI.TestInterface;
  1134. var
  1135. context: TRttiContext;
  1136. t: TRttiType;
  1137. ti1, ti2: TRttiInterfaceType;
  1138. methods: {$ifdef fpc}specialize{$endif} TArray<TRttiMethod>;
  1139. params: {$ifdef fpc}specialize{$endif} TArray<TRttiParameter>;
  1140. method: TRttiMethod;
  1141. param: TRttiParameter;
  1142. flag: TParamFlag;
  1143. begin
  1144. context := TRttiContext.Create;
  1145. try
  1146. t := context.GetType(TypeInfo(IInterface));
  1147. Check(t is TRttiInterfaceType, 'Type is not an interface type');
  1148. Check(not Assigned(t.BaseType), 'Base type is assigned');
  1149. ti1 := TRttiInterfaceType(t);
  1150. Check(not Assigned(ti1.BaseType), 'Base type is assigned');
  1151. methods := t.GetMethods;
  1152. CheckEquals(0, Length(methods), 'Overall method count does not match');
  1153. methods := t.GetDeclaredMethods;
  1154. CheckEquals(0, Length(methods), 'Declared method conut does not match');
  1155. t := context.GetType(TypeInfo(ITestInterface));
  1156. Check(t is TRttiInterfaceType, 'Type is not an interface type');
  1157. Check(Assigned(t.BaseType), 'Base type is not assigned');
  1158. Check(t.BaseType = TRttiType(ti1), 'Base type does not match');
  1159. ti2 := TRttiInterfaceType(t);
  1160. Check(Assigned(ti2.BaseType), 'Base type is not assigned');
  1161. Check(ti2.BaseType = ti1, 'Base type does not match');
  1162. methods := t.GetMethods;
  1163. CheckEquals(4, Length(methods), 'Overall method count does not match');
  1164. methods := t.GetDeclaredMethods;
  1165. CheckEquals(4, Length(methods), 'Declared method count does not match');
  1166. method := methods[0];
  1167. CheckEquals(method.Name, 'Test', 'Method name of Test does not match');
  1168. Check(method.CallingConvention = DefaultCC, 'Calling convention of Test does not match');
  1169. Check(method.MethodKind = mkProcedure, 'Method kind of Test does not match');
  1170. Check(method.DispatchKind = dkInterface, 'Dispatch kind of Test does not match');
  1171. Check(not Assigned(method.CodeAddress), 'Code address of Test is not Nil');
  1172. CheckEquals(method.VirtualIndex, 3, 'Virtual index of Test does not match');
  1173. Check(not Assigned(method.ReturnType), 'Return type of Test is not Nil');
  1174. params := method.GetParameters;
  1175. CheckEquals(0, Length(params), 'Parameter count of Test does not match');
  1176. method := methods[1];
  1177. CheckEquals(method.Name, 'Test2', 'Method name of Test2 does not match');
  1178. Check(method.CallingConvention = DefaultCC, 'Calling convention of Test2 does not match');
  1179. Check(method.MethodKind = mkFunction, 'Method kind of Test2 does not match');
  1180. Check(method.DispatchKind = dkInterface, 'Dispatch kind of Test2 does not match');
  1181. Check(not Assigned(method.CodeAddress), 'Code address of Test2 is not Nil');
  1182. CheckEquals(method.VirtualIndex, 4, 'Virtual index of Test2 does not match');
  1183. Check(Assigned(method.ReturnType), 'Return type of Test2 is Nil');
  1184. Check(method.ReturnType.TypeKind = tkInteger, 'Return type of Test2 is not an ordinal');
  1185. params := method.GetParameters;
  1186. CheckEquals(0, Length(params), 'Parameter count of Test2 does not match');
  1187. method := methods[2];
  1188. CheckEquals(method.Name, 'Test3', 'Method name of Test3 does not match');
  1189. Check(method.CallingConvention = DefaultCC, 'Calling convention of Test3 does not match');
  1190. Check(method.MethodKind = mkProcedure, 'Method kind of Test3 does not match');
  1191. Check(method.DispatchKind = dkInterface, 'Dispatch kind of Test3 does not match');
  1192. Check(not Assigned(method.CodeAddress), 'Code address of Test3 is not Nil');
  1193. CheckEquals(method.VirtualIndex, 5, 'Virtual index of Test3 does not match');
  1194. Check(not Assigned(method.ReturnType), 'Return type of Test3 is not Nil');
  1195. params := method.GetParameters;
  1196. CheckEquals(4, Length(params), 'Parameter count of Test3 does not match');
  1197. param := params[0];
  1198. CheckEquals(param.Name, 'aArg1', 'Parameter name of Test3.aArg1 does not match');
  1199. Check(param.Flags = [], 'Parameter flags of Test3.aArg1 do not match');
  1200. Check(Assigned(param.ParamType), 'Parameter type of Test3.aArg1 is Nil');
  1201. Check(param.ParamType.TypeKind = tkInteger, 'Parameter type of Test3.aArg1 is not an ordinal');
  1202. param := params[1];
  1203. CheckEquals(param.Name, 'aArg2', 'Parameter name of Test3.aArg2 does not match');
  1204. Check(param.Flags = [pfConst], 'Parameter flags of Test3.aArg2 do not match');
  1205. Check(Assigned(param.ParamType), 'Parameter type of Test3.aArg2 is Nil');
  1206. Check(param.ParamType.TypeKind = tkAnsiString, 'Parameter type of Test3.aArg2 is not a string');
  1207. param := params[2];
  1208. CheckEquals(param.Name, 'aArg3', 'Parameter name of Test3.aArg3 does not match');
  1209. Check(param.Flags = [pfVar], 'Parameter flags of Test3.aArg3 do not match');
  1210. Check(Assigned(param.ParamType), 'Parameter type of Test3.aArg3 is Nil');
  1211. Check(param.ParamType.TypeKind = {$ifdef fpc}tkBool{$else}tkEnumeration{$endif}, 'Parameter type of Test3.aArg3 is not a boolean');
  1212. param := params[3];
  1213. CheckEquals(param.Name, 'aArg4', 'Parameter name of Test3.aArg4 does not match');
  1214. Check(param.Flags = [pfOut], 'Parameter flags of Test3.aArg4 do not match');
  1215. Check(Assigned(param.ParamType), 'Parameter type of Test3.aArg4 is Nil');
  1216. Check(param.ParamType.TypeKind = tkInteger, 'Parameter type of Test3.aArg4 is not a string');
  1217. method := methods[3];
  1218. CheckEquals(method.Name, 'Test4', 'Method name of Test4 does not match');
  1219. Check(method.CallingConvention = DefaultCC, 'Calling convention of Test4 does not match');
  1220. Check(method.MethodKind = mkFunction, 'Method kind of Test4 does not match');
  1221. Check(method.DispatchKind = dkInterface, 'Dispatch kind of Test4 does not match');
  1222. Check(not Assigned(method.CodeAddress), 'Code address of Test4 is not Nil');
  1223. CheckEquals(method.VirtualIndex, 6, 'Virtual index of Test4 does not match');
  1224. Check(Assigned(method.ReturnType), 'Return type of Test4 is not Nil');
  1225. Check(method.ReturnType.TypeKind = tkAnsiString, 'Return type of Test4 is not a string');
  1226. params := method.GetParameters;
  1227. CheckEquals(2, Length(params), 'Parameter count of Test4 does not match');
  1228. param := params[0];
  1229. CheckEquals(param.Name, 'aArg1', 'Parameter name of Test4.aArg1 does not match');
  1230. Check(param.Flags = [pfArray, pfReference], 'Parameter flags of Test4.aArg1 do not match');
  1231. Check(Assigned(param.ParamType), 'Parameter type of Test4.aArg1 is Nil');
  1232. Check(param.ParamType.TypeKind = tkInteger, 'Parameter type of Test4.aArg1 is not an ordinal');
  1233. param := params[1];
  1234. CheckEquals(param.Name, 'aArg2', 'Parameter name of Test4.aArg2 does not match');
  1235. Check(param.Flags = [pfArray, pfReference], 'Parameter flags of Test4.aArg2 do not match');
  1236. Check(Assigned(param.ParamType), 'Parameter type of Test4.aArg2 is Nil');
  1237. Check(param.ParamType.TypeKind = tkRecord, 'Parameter type of Test4.aArg2 is not a record');
  1238. finally
  1239. context.Free;
  1240. end;
  1241. end;
  1242. procedure TTestRTTI.TestRawThunk;
  1243. var
  1244. intf: IInterface;
  1245. begin
  1246. { we test the raw thunking by instantiating a TVirtualInterface of IInterface }
  1247. { this does not require a function call manager as the thunking is implemented
  1248. directly inside the RTTI unit }
  1249. try
  1250. intf := TVirtualInterface.Create(PTypeInfo(TypeInfo(IInterface))) as IInterface;
  1251. except
  1252. on e: ENotImplemented do
  1253. Ignore('RawThunk not implemented');
  1254. end;
  1255. { if all went well QueryInterface and _AddRef were called and now we call
  1256. _Release as well }
  1257. intf := Nil;
  1258. end;
  1259. {$ifdef fpc}
  1260. procedure TTestRTTI.TestInterfaceRaw;
  1261. var
  1262. context: TRttiContext;
  1263. t: TRttiType;
  1264. ti: TRttiInterfaceType;
  1265. begin
  1266. context := TRttiContext.Create;
  1267. try
  1268. t := context.GetType(TypeInfo(ICORBATest));
  1269. Check(t is TRttiInterfaceType, 'Type is not a raw interface type');
  1270. Check(not Assigned(t.BaseType), 'Base type is assigned');
  1271. ti := TRttiInterfaceType(t);
  1272. Check(not Assigned(ti.BaseType), 'Base type is assigned');
  1273. finally
  1274. context.Free;
  1275. end;
  1276. end;
  1277. {$endif}
  1278. procedure TTestRTTI.TestArray;
  1279. var
  1280. context: TRttiContext;
  1281. t, el: TRttiType;
  1282. a: TRttiArrayType;
  1283. o: TRttiOrdinalType;
  1284. begin
  1285. context := TRttiContext.Create;
  1286. try
  1287. t := context.GetType(PTypeInfo(TypeInfo(TArrayOfLongintStatic)));
  1288. Check(t is TRttiArrayType, 'Type is not a TRttiArrayType');
  1289. a := TRttiArrayType(t);
  1290. CheckEquals(1, a.DimensionCount, 'Dimension count does not match');
  1291. CheckEquals(4, a.TotalElementCount, 'Total element count does not match');
  1292. el := a.ElementType;
  1293. Check(el is TRttiOrdinalType, 'Element type is not a TRttiOrdinalType');
  1294. Check(el = context.GetType(PTypeInfo(TypeInfo(LongInt))), 'Element type is not a LongInt');
  1295. t := a.Dimensions[0];
  1296. {$ifdef fpc}
  1297. Check(t is TRttiOrdinalType, 'Index type is not a TRttiOrdinalType');
  1298. o := TRttiOrdinalType(t);
  1299. { Currently this is a full type :/ }
  1300. {CheckEquals(0, o.MinValue, 'Minimum value of 1st dimension does not match');
  1301. CheckEquals(3, o.MaxValue, 'Maximum value of 1st dimension does not match');}
  1302. {$else}
  1303. Check(t = Nil, 'Index type is not Nil');
  1304. {$endif}
  1305. t := context.GetType(PTypeInfo(TypeInfo(TArrayOfLongint2DStatic)));
  1306. Check(t is TRttiArrayType, 'Type is not a TRttiArrayType');
  1307. a := TRttiArrayType(t);
  1308. CheckEquals(2, a.DimensionCount, 'Dimension count does not match');
  1309. CheckEquals(4 * 3, a.TotalElementCount, 'Total element count does not match');
  1310. el := a.ElementType;
  1311. Check(el is TRttiOrdinalType, 'Element type is not a TRttiOrdinalType');
  1312. Check(el = context.GetType(PTypeInfo(TypeInfo(LongInt))), 'Element type is not a LongInt');
  1313. t := a.Dimensions[0];
  1314. {$ifdef fpc}
  1315. Check(t is TRttiOrdinalType, 'Index type is not a TRttiOrdinalType');
  1316. o := TRttiOrdinalType(t);
  1317. { Currently this is a full type :/ }
  1318. {CheckEquals(0, o.MinValue, 'Minimum value of 1st dimension does not match');
  1319. CheckEquals(3, o.MaxValue, 'Maximum value of 1st dimension does not match');}
  1320. {$else}
  1321. Check(t = Nil, 'Index type is not Nil');
  1322. {$endif}
  1323. t := a.Dimensions[1];
  1324. {$ifdef fpc}
  1325. Check(t is TRttiOrdinalType, 'Index type is not a TRttiOrdinalType');
  1326. o := TRttiOrdinalType(t);
  1327. { Currently this is a full type :/ }
  1328. {CheckEquals(2, o.MinValue, 'Minimum value of 1st dimension does not match');
  1329. CheckEquals(4, o.MaxValue, 'Maximum value of 1st dimension does not match');}
  1330. {$else}
  1331. Check(t = Nil, 'Index type is not Nil');
  1332. {$endif}
  1333. finally
  1334. context.Free;
  1335. end;
  1336. end;
  1337. procedure TTestRTTI.TestDynArray;
  1338. var
  1339. context: TRttiContext;
  1340. t, el: TRttiType;
  1341. a: TRttiDynamicArrayType;
  1342. begin
  1343. context := TRttiContext.Create;
  1344. try
  1345. t := context.GetType(PTypeInfo(TypeInfo(TArrayOfLongintDyn)));
  1346. Check(t is TRttiDynamicArrayType, 'Type is not a TRttiDynamicArrayType');
  1347. a := TRttiDynamicArrayType(t);
  1348. CheckEquals('tests.rtti.types', LowerCase(a.DeclaringUnitName), 'Unit type does not match for dynamic array');
  1349. CheckEquals(a.ElementSize, SizeUInt(SizeOf(LongInt)), 'Element size does not match for dynamic array');
  1350. el := a.ElementType;
  1351. Check(el is TRttiOrdinalType, 'Element type is not a TRttiOrdinalType');
  1352. Check(el = context.GetType(PTypeInfo(TypeInfo(LongInt))), 'Element type is not a LongInt');
  1353. { ToDo: check OLE type }
  1354. finally
  1355. context.Free;
  1356. end;
  1357. end;
  1358. procedure TTestRTTI.TestProcVar;
  1359. var
  1360. context: TRttiContext;
  1361. t: TRttiType;
  1362. p: TRttiProcedureType;
  1363. params: {$ifdef fpc}specialize{$endif} TArray<TRttiParameter>;
  1364. begin
  1365. context := TRttiContext.Create;
  1366. try
  1367. t := context.GetType(PTypeInfo(TypeInfo(TTestProc)));
  1368. Check(Assigned(t), 'Rtti Type is Nil');
  1369. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1370. Check(t is TRttiProcedureType, 'Rtti Type is not a procedure type');
  1371. p := t as TRttiProcedureType;
  1372. Check(p.CallingConvention = DefaultCC, 'Calling convention does not match');
  1373. Check(not Assigned(p.ReturnType), 'Return type is assigned');
  1374. CheckEquals(0, Length(p.GetParameters), 'Procedure variable has parameters');
  1375. t := context.GetType(PTypeInfo(TypeInfo(TTestFunc1)));
  1376. Check(Assigned(t), 'Rtti Type is Nil');
  1377. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1378. Check(t is TRttiProcedureType, 'Rtti Type is not a procedure type');
  1379. p := t as TRttiProcedureType;
  1380. Check(p.CallingConvention = DefaultCC, 'Calling convention does not match');
  1381. Check(Assigned(p.ReturnType), 'Return type is not assigned');
  1382. //Check(p.ReturnType is TRttiOrdinalType, 'Return type is not an ordinal type');
  1383. CheckEquals(0, Length(p.GetParameters), 'Procedure variable has parameters');
  1384. t := context.GetType(PTypeInfo(TypeInfo(TTestFunc2)));
  1385. Check(Assigned(t), 'Rtti Type is Nil');
  1386. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1387. Check(t is TRttiProcedureType, 'Rtti Type is not a procedure type');
  1388. p := t as TRttiProcedureType;
  1389. Check(p.CallingConvention = DefaultCC, 'Calling convention does not match');
  1390. Check(Assigned(p.ReturnType), 'Return type is not assigned');
  1391. Check(p.ReturnType is TRttiStringType, 'Return type is not a string type');
  1392. params := p.GetParameters;
  1393. CheckEquals(2, Length(params), 'Procedure variable has incorrect amount of parameters');
  1394. Check(params[0].ParamType.TypeKind in [tkInteger, tkInt64], 'Parameter 1 is not an ordinal type');
  1395. //Check(params[0].ParamType is TRttiOrdinalType, 'Parameter 1 is not an ordinal type');
  1396. Check(pfArray in params[1].Flags, 'Parameter 2 is not an array');
  1397. Check(params[1].ParamType.TypeKind in [tkInteger, tkInt64], 'Parameter 2 is not an ordinal array');
  1398. finally
  1399. context.Free;
  1400. end;
  1401. end;
  1402. procedure TTestRTTI.TestMethod;
  1403. var
  1404. context: TRttiContext;
  1405. t: TRttiType;
  1406. m: TRttiMethodType;
  1407. params: {$ifdef fpc}specialize{$endif} TArray<TRttiParameter>;
  1408. begin
  1409. context := TRttiContext.Create;
  1410. try
  1411. t := context.GetType(PTypeInfo(TypeInfo(TTestMethod)));
  1412. Check(Assigned(t), 'Rtti Type is Nil');
  1413. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1414. Check(t is TRttiMethodType, 'Rtti Type is not a method type');
  1415. m := t as TRttiMethodType;
  1416. Check(m.CallingConvention = DefaultCC, 'Calling convention does not match');
  1417. Check(not Assigned(m.ReturnType), 'Return type is assigned');
  1418. CheckEquals(0, Length(m.GetParameters), 'Method variable has parameters');
  1419. t := context.GetType(PTypeInfo(TypeInfo(TTestMethod1)));
  1420. Check(Assigned(t), 'Rtti Type is Nil');
  1421. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1422. Check(t is TRttiMethodType, 'Rtti Type is not a method type');
  1423. m := t as TRttiMethodType;
  1424. Check(m.CallingConvention = DefaultCC, 'Calling convention does not match');
  1425. Check(Assigned(m.ReturnType), 'Return type is not assigned');
  1426. //Check(p.ReturnType is TRttiOrdinalType, 'Return type is not an ordinal type');
  1427. CheckEquals(0, Length(m.GetParameters), 'Method variable has parameters');
  1428. t := context.GetType(PTypeInfo(TypeInfo(TTestMethod2)));
  1429. Check(Assigned(t), 'Rtti Type is Nil');
  1430. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1431. Check(t is TRttiMethodType, 'Rtti Type is not a method type');
  1432. m := t as TRttiMethodType;
  1433. Check(m.CallingConvention = DefaultCC, 'Calling convention does not match');
  1434. Check(Assigned(m.ReturnType), 'Return type is not assigned');
  1435. Check(m.ReturnType is TRttiStringType, 'Return type is not a string type');
  1436. params := m.GetParameters;
  1437. CheckEquals(2, Length(params), 'Method variable has incorrect amount of parameters');
  1438. Check(params[0].ParamType.TypeKind in [tkInteger, tkInt64], 'Parameter 1 is not an ordinal type');
  1439. //Check(params[0].ParamType is TRttiOrdinalType, 'Parameter 1 is not an ordinal type');
  1440. Check(pfArray in params[1].Flags, 'Parameter 2 is not an array');
  1441. Check(params[1].ParamType.TypeKind in [tkInteger, tkInt64], 'Parameter 2 is not an ordinal array');
  1442. finally
  1443. context.Free;
  1444. end;
  1445. end;
  1446. { TTestExtendedRTTI }
  1447. procedure TTestExtendedRTTI.AssertEquals(Msg: String; aExpected, aActual: TMemberVisibility);
  1448. begin
  1449. AssertEquals(Msg,GetEnumName(TypeInfo(TMemberVisibility),Ord(aExpected)),
  1450. GetEnumName(TypeInfo(TMemberVisibility),Ord(aActual)));
  1451. end;
  1452. procedure TTestExtendedRTTI.AssertEquals(Msg: String; aExpected, aActual: TTypeKind);
  1453. begin
  1454. AssertEquals(Msg,GetEnumName(TypeInfo(TTypeKind),Ord(aExpected)),
  1455. GetEnumName(TypeInfo(TTypeKind),Ord(aActual)));
  1456. end;
  1457. procedure TTestExtendedRTTI.Setup;
  1458. begin
  1459. Inherited;
  1460. FCtx:=TRttiContext.Create;
  1461. FCtx.UsePublishedOnly:=False;
  1462. end;
  1463. procedure TTestExtendedRTTI.TearDown;
  1464. begin
  1465. FCtx.Free;
  1466. inherited TearDown;
  1467. end;
  1468. Procedure TTestExtendedRTTI.CheckField(aIdx : Integer; aData: TRttiField; aName : String; aKind : TTypeKind; aVisibility : TMemberVisibility; aStrict : Boolean = False);
  1469. Var
  1470. Msg : String;
  1471. begin
  1472. Msg:='Checking field '+IntToStr(aIdx)+' ('+aName+') ';
  1473. AssertNotNull(Msg+'Have data',AData);
  1474. AssertEquals(Msg+'name',aName,aData.Name);
  1475. AssertEquals(Msg+'kind',aKind,aData.FieldType.TypeKind);
  1476. AssertEquals(Msg+'visibility',aVisibility,aData.Visibility);
  1477. AssertEquals(Msg+'strict',aStrict,aData.StrictVisibility);
  1478. end;
  1479. Procedure TTestExtendedRTTI.CheckProperty(aIdx : Integer; aData: TRttiProperty; aName : String; aKind : TTypeKind; aVisibility : TMemberVisibility; isStrict : Boolean = False);
  1480. Var
  1481. Msg : String;
  1482. begin
  1483. Msg:='Checking prop '+IntToStr(aIdx)+' ('+aName+') ';
  1484. AssertNotNull(Msg+'Have data',AData);
  1485. AssertEquals(Msg+'name',aName, aData.Name);
  1486. AssertEquals(Msg+'kind',aKind, aData.PropertyType.TypeKind);
  1487. AssertEquals(Msg+'visibility',aVisibility,aData.Visibility);
  1488. AssertEquals(Msg+'strict',isStrict,aData.StrictVisibility);
  1489. end;
  1490. Procedure TTestExtendedRTTI.CheckMethod(aPrefix : string; aIdx : Integer; aData: TRttiMethod; aName : String; aVisibility : TMemberVisibility; aStrict : Boolean = False);
  1491. Var
  1492. Msg : String;
  1493. begin
  1494. Msg:=aPrefix+': Checking method '+IntToStr(aIdx)+' ('+aName+') ';
  1495. AssertNotNull(Msg+'Have data',AData);
  1496. AssertEquals(Msg+'name',aData.Name,aName);
  1497. AssertEquals(Msg+'visibility',aVisibility,aData.Visibility);
  1498. AssertEquals(Msg+'strict',aData.StrictVisibility,aStrict);
  1499. end;
  1500. procedure TTestClassExtendedRTTI.TestFields;
  1501. Var
  1502. Obj : TRttiObject;
  1503. RttiData : TRttiInstanceType absolute obj;
  1504. A : TRttiFieldArray;
  1505. t : TFieldRTTI;
  1506. begin
  1507. Obj:=FCtx.GetType(TFieldRTTI.ClassInfo);
  1508. AssertEquals('Correct class type',TRttiInstanceType,Obj.ClassType);
  1509. A:=RttiData.GetFields;
  1510. AssertEquals('Class field Count',10,Length(A));
  1511. CheckField(0, A[0],'FPrivateA',tkInteger,mvPrivate);
  1512. CheckField(1, A[1],'FPrivateB',tkInteger,mvPrivate,True);
  1513. CheckField(2, A[2],'FProtectedA',tkInteger,mvProtected);
  1514. CheckField(3, A[3],'FProtectedB',tkInteger,mvProtected,True);
  1515. CheckField(4, A[4],'FPublicA',tkInteger,mvPublic);
  1516. CheckField(5, A[5],'FPublicB',tkInteger,mvPublic);
  1517. CheckField(6, A[6],'FPublishedA',tkInteger,mvPrivate);
  1518. CheckField(7, A[7],'FPublishedB',tkInteger,mvPrivate);
  1519. CheckField(8, A[8],'FPublishedC',tkClass,mvPublished);
  1520. CheckField(9, A[9],'FPublishedD',tkClass,mvPublished);
  1521. t := TFieldRTTI.Create;
  1522. AssertEquals('Legacy Field 0', A[8].Offset, Integer(PByte(t.FieldAddress('FPublishedC')) - PByte(t)));
  1523. AssertEquals('Legacy Field 1', A[9].Offset, Integer(PByte(t.FieldAddress('FPublishedD')) - PByte(t)));
  1524. T.Free;
  1525. end;
  1526. procedure TTestClassExtendedRTTI.TestDeclaredFields;
  1527. Var
  1528. Obj : TRttiObject;
  1529. RttiData : TRttiInstanceType absolute obj;
  1530. Obj2 : TRttiObject;
  1531. RttiData2 : TRttiInstanceType absolute obj2;
  1532. A : TRttiFieldArray;
  1533. I : Integer;
  1534. begin
  1535. Obj:=FCtx.GetType(TFieldRTTIChild.ClassInfo);
  1536. AssertEquals('Correct class type',TRttiInstanceType,Obj.ClassType);
  1537. Obj2:=FCtx.GetType(TFieldRTTI.ClassInfo);
  1538. AssertEquals('Correct class type',TRttiInstanceType,Obj2.ClassType);
  1539. A:=RttiData.GetFields;
  1540. AssertEquals('Class field Count',11,Length(A));
  1541. For I:=1 to 10 do
  1542. AssertSame('Field parent'+IntToStr(i)+' is parent class', Obj2,A[I].Parent);
  1543. A:=RttiData.GetDeclaredFields;
  1544. AssertEquals('Class declared field Count',1,Length(A));
  1545. AssertSame('Declared Field parent is sels', Obj,A[0].Parent);
  1546. end;
  1547. procedure TTestClassExtendedRTTI.TestProperties;
  1548. Var
  1549. A : TRttiPropertyArray;
  1550. Obj : TRttiObject;
  1551. RttiData : TRttiInstanceType absolute obj;
  1552. aCount : Integer;
  1553. begin
  1554. Obj:=FCtx.GetType(TFieldRTTI.ClassInfo);
  1555. AssertEquals('Correct class type',TRttiInstanceType,Obj.ClassType);
  1556. A:=RttiData.GetProperties;
  1557. aCount:=Length(A);
  1558. AssertEquals('Property Count',8,aCount);
  1559. CheckProperty(0, A[0],'PrivateA',tkInteger,mvPrivate);
  1560. CheckProperty(1, A[1],'PrivateB',tkInteger,mvPrivate,True);
  1561. CheckProperty(2, A[2],'ProtectedA',tkInteger,mvProtected);
  1562. CheckProperty(3, A[3],'ProtectedB',tkInteger,mvProtected,True);
  1563. CheckProperty(4, A[4],'PublicA',tkInteger,mvPublic);
  1564. CheckProperty(5, A[5],'PublicB',tkInteger,mvPublic);
  1565. CheckProperty(6, A[6],'PublishedA',tkInteger,mvPublished);
  1566. CheckProperty(7, A[7],'PublishedB',tkInteger,mvPublished);
  1567. end;
  1568. procedure TTestClassExtendedRTTI.TestDeclaredMethods;
  1569. Var
  1570. A : TRttiMethodArray;
  1571. Obj : TRttiObject;
  1572. RttiData : TRttiInstanceType absolute obj;
  1573. Parms : TRttiParameterArray;
  1574. aCount : Integer;
  1575. begin
  1576. Obj:=FCtx.GetType(TMethodClassRTTI.ClassInfo);
  1577. AssertEquals('Correct class type',TRttiInstanceType,Obj.ClassType);
  1578. A:=RttiData.GetDeclaredMethods;
  1579. aCount:=Length(A);
  1580. AssertEquals('Full Count',12,aCount);
  1581. CheckMethod('Full',0, A[0],'PrivateMethodA',mvPrivate);
  1582. CheckMethod('Full',1, A[1],'PrivateMethodB',mvPrivate,True);
  1583. CheckMethod('Full',2, A[2],'PrivateMethodC',mvPrivate);
  1584. CheckMethod('Full',3, A[3],'ProtectedMethodA',mvProtected);
  1585. CheckMethod('Full',4, A[4],'ProtectedMethodB',mvProtected,True);
  1586. CheckMethod('Full',5, A[5],'ProtectedMethodC',mvProtected);
  1587. CheckMethod('Full',6, A[6],'PublicMethodA',mvPublic);
  1588. CheckMethod('Full',7, A[7],'PublicMethodB',mvPublic);
  1589. CheckMethod('Full',8, A[8],'PublicMethodC',mvPublic);
  1590. CheckMethod('Full',9, A[9],'PublishedMethodA',mvPublished);
  1591. CheckMethod('Full',10, A[10],'PublishedMethodB',mvPublished);
  1592. CheckMethod('Full',11, A[11],'PublishedMethodC',mvPublished);
  1593. Parms:=A[9].GetParameters;
  1594. AssertEquals('Parameter length',1,Length(Parms));
  1595. AssertEquals('Parameter name','a',Parms[0].Name);
  1596. end;
  1597. procedure TTestClassExtendedRTTI.TestMethods;
  1598. Var
  1599. A : TRttiMethodArray;
  1600. Obj : TRttiObject;
  1601. RttiData : TRttiInstanceType absolute obj;
  1602. aCount : Integer;
  1603. begin
  1604. Obj:=FCtx.GetType(TAdditionalMethodClassRTTI.ClassInfo);
  1605. AssertEquals('Correct class type',TRttiInstanceType,Obj.ClassType);
  1606. A:=RttiData.GetMethods;
  1607. aCount:=Length(A);
  1608. AssertEquals('Full Count',13,aCount);
  1609. CheckMethod('Full',0, A[0],'PublicAdditionalMethod',mvPublic);
  1610. A:=RttiData.GetDeclaredMethods;
  1611. aCount:=Length(A);
  1612. AssertEquals('Full declared Count',1,aCount);
  1613. CheckMethod('Full declared',1, A[0],'PublicAdditionalMethod',mvPublic);
  1614. end;
  1615. procedure TTestClassExtendedRTTI.TestMethodByAddress;
  1616. var
  1617. Obj : TRttiObject;
  1618. RttiData : TRttiInstanceType absolute obj;
  1619. M1,M2 : TRttiMethod;
  1620. begin
  1621. Obj:=FCtx.GetType(TAdditionalMethodClassRTTI.ClassInfo);
  1622. M1:=RttiData.GetMethod('PublicAdditionalMethod');
  1623. AssertNotNull('have method',m1);
  1624. M2:=RttiData.GetMethod(@TAdditionalMethodClassRTTI.PublicAdditionalMethod);
  1625. AssertSame('Correct method ',M1,M2);
  1626. end;
  1627. procedure TTestClassExtendedRTTI.TestMethodsInherited;
  1628. Var
  1629. A : TRttiMethodArray;
  1630. Obj,Obj2 : TRttiObject;
  1631. RttiData : TRttiInstanceType absolute obj;
  1632. RttiData2 : TRttiInstanceType absolute obj2;
  1633. i,aCount : Integer;
  1634. begin
  1635. Obj:=FCtx.GetType(TAdditionalMethodClassRTTI.ClassInfo);
  1636. AssertEquals('Correct class type',TRttiInstanceType,Obj.ClassType);
  1637. Obj2:=FCtx.GetType(TMethodClassRTTI.ClassInfo);
  1638. AssertEquals('Correct class type',TRttiInstanceType,Obj.ClassType);
  1639. A:=RttiData.GetMethods;
  1640. aCount:=Length(A);
  1641. AssertEquals('Full Count',13,aCount);
  1642. For I:=1 to 12 do
  1643. AssertSame('Parent is RTTI of parent class',Obj2,A[I].Parent);
  1644. A:=RttiData.GetDeclaredMethods;
  1645. aCount:=Length(A);
  1646. AssertEquals('Full declared Count',1,aCount);
  1647. CheckMethod('Full declared',1, A[0],'PublicAdditionalMethod',mvPublic);
  1648. AssertSame('Parent is RTTI of parent class',Obj,A[0].Parent);
  1649. end;
  1650. procedure TTestClassExtendedRTTI.TestPrivateFieldAttributes;
  1651. var
  1652. Obj : TRttiObject;
  1653. RttiData : TRttiInstanceType absolute obj;
  1654. Attrs : TCustomAttributeArray;
  1655. Fld : TRttiField;
  1656. O : TCustomAttribute;
  1657. M2 : My2Attribute absolute O;
  1658. begin
  1659. Obj:=FCtx.GetType(TypeInfo(TFieldObject));
  1660. AssertEquals('Correct class type',TRttiInstanceType,Obj.ClassType);
  1661. Fld:=RttiData.GetField('PrivateField');
  1662. AssertNotNull('Have field',Fld);
  1663. Attrs:=Fld.GetAttributes;
  1664. AssertNotNull('Have attribute data',Pointer(Attrs));
  1665. AssertEquals('attribute count',3,Length(Attrs));
  1666. AssertEquals('Attribute 1 name','WeakAttribute',Attrs[0].ClassName);
  1667. AssertEquals('Attribute 2 name','MyAttribute',Attrs[1].ClassName);
  1668. AssertEquals('Attribute 2 name','My2Attribute',Attrs[2].ClassName);
  1669. O:=Attrs[2];
  1670. AssertNotNull('Attribute class ',O);
  1671. AssertEquals('Attribute class ',O.ClassType,My2Attribute);
  1672. AssertEquals('Attribute value ',2,M2.Int);
  1673. end;
  1674. procedure TTestClassExtendedRTTI.TestProtectedFieldAttributes;
  1675. var
  1676. Obj : TRttiObject;
  1677. RttiData : TRttiInstanceType absolute obj;
  1678. Attrs : TCustomAttributeArray;
  1679. Fld : TRttiField;
  1680. O : TCustomAttribute;
  1681. M2 : My2Attribute absolute O;
  1682. begin
  1683. Obj:=FCtx.GetType(TypeInfo(TFieldObject));
  1684. AssertEquals('Correct class type',TRttiInstanceType,Obj.ClassType);
  1685. Fld:=RttiData.GetField('ProtectedField');
  1686. AssertNotNull('Have field',Fld);
  1687. Attrs:=Fld.GetAttributes;
  1688. AssertNotNull('Have attribute data',Pointer(Attrs));
  1689. AssertEquals('attribute count',1,Length(Attrs));
  1690. AssertEquals('Attribute 1 name','My2Attribute',Attrs[0].ClassName);
  1691. O:=Attrs[0];
  1692. AssertNotNull('Attribute class ',O);
  1693. AssertEquals('Attribute class ',O.ClassType,My2Attribute);
  1694. AssertEquals('Attribute value ',3,M2.Int);
  1695. end;
  1696. procedure TTestClassExtendedRTTI.TestPublicFieldAttributes;
  1697. var
  1698. Obj : TRttiObject;
  1699. RttiData : TRttiInstanceType absolute obj;
  1700. Attrs : TCustomAttributeArray;
  1701. Fld : TRttiField;
  1702. O : TCustomAttribute;
  1703. M3 : My3Attribute absolute O;
  1704. aCount : Integer;
  1705. begin
  1706. Obj:=FCtx.GetType(TypeInfo(TFieldObject));
  1707. AssertEquals('Correct class type',TRttiInstanceType,Obj.ClassType);
  1708. aCount:=0;
  1709. For Fld in RttiData.GetFields do
  1710. if Fld.Visibility=mvPublic then
  1711. inc(aCount);
  1712. AssertEquals('Field count',3,aCount);
  1713. // PublicField
  1714. Fld:=RttiData.GetField('PublicField');
  1715. AssertNotNull('Have field',Fld);
  1716. Attrs:=Fld.GetAttributes;
  1717. AssertNotNull('Have attribute data',Pointer(Attrs));
  1718. AssertEquals('attribute count',1,Length(Attrs));
  1719. AssertEquals('Attribute 1 name','My3Attribute',Attrs[0].ClassName);
  1720. O:=Attrs[0];
  1721. AssertNotNull('Attribute class ',O);
  1722. AssertEquals('Attribute class ',O.ClassType,My3Attribute);
  1723. AssertEquals('Attribute value ',4,M3.Int);
  1724. // A
  1725. Fld:=RttiData.GetField('A');
  1726. AssertNotNull('A Have field',Fld);
  1727. Attrs:=Fld.GetAttributes;
  1728. AssertNotNull('A Have attribute data',Pointer(Attrs));
  1729. AssertEquals('A Attribute count',1,Length(Attrs));
  1730. AssertEquals('A Attribute 1 name','My3Attribute',Attrs[0].ClassName);
  1731. O:=Attrs[0];
  1732. AssertNotNull('A: Attribute class ',O);
  1733. AssertEquals('A: Attribute class ',O.ClassType,My3Attribute);
  1734. AssertEquals('A: Attribute value ',4,M3.Int);
  1735. // B
  1736. Fld:=RttiData.GetField('B');
  1737. AssertNotNull('B Have field',Fld);
  1738. Attrs:=Fld.GetAttributes;
  1739. AssertNotNull('B Have attribute data',Pointer(Attrs));
  1740. AssertEquals('A Attribute count',1,Length(Attrs));
  1741. AssertEquals('A Attribute 1 name','My3Attribute',Attrs[0].ClassName);
  1742. O:=Attrs[0];
  1743. AssertNotNull('B: Attribute class ',O);
  1744. AssertEquals('B: Attribute class ',O.ClassType,My3Attribute);
  1745. AssertEquals('B: Attribute value ',4,M3.Int);
  1746. end;
  1747. procedure TTestClassExtendedRTTI.TestPrivatePropertyAttributes;
  1748. var
  1749. Obj : TRttiObject;
  1750. RttiData : TRttiInstanceType absolute obj;
  1751. Attrs : TCustomAttributeArray;
  1752. Prop : TRttiProperty;
  1753. O : TCustomAttribute;
  1754. aCount : Integer;
  1755. M2 : My2Attribute absolute O;
  1756. begin
  1757. Obj:=FCtx.GetType(TypeInfo(TPropertyObject));
  1758. AssertEquals('Correct class type',TRttiInstanceType,Obj.ClassType);
  1759. aCount:=0;
  1760. Prop:=RttiData.GetProperty('PrivateProperty');
  1761. AssertNotNull('Have property',Prop);
  1762. Attrs:=Prop.GetAttributes;
  1763. AssertNotNull('Have attribute data',Pointer(Attrs));
  1764. AssertEquals('attribute count',3,Length(Attrs));
  1765. AssertEquals('Attribute 1 name','WeakAttribute',Attrs[0].ClassName);
  1766. AssertEquals('Attribute 2 name','MyAttribute',Attrs[1].ClassName);
  1767. AssertEquals('Attribute 2 name','My2Attribute',Attrs[2].ClassName);
  1768. O:=Attrs[2];
  1769. AssertNotNull('Attribute class ',O);
  1770. AssertEquals('Attribute class ',O.ClassType,My2Attribute);
  1771. AssertEquals('Attribute value ',2,M2.Int);
  1772. end;
  1773. procedure TTestClassExtendedRTTI.TestProtectedPropertyAttributes;
  1774. var
  1775. Obj : TRttiObject;
  1776. RttiData : TRttiInstanceType absolute obj;
  1777. Attrs : TCustomAttributeArray;
  1778. Prop : TRttiProperty;
  1779. O : TCustomAttribute;
  1780. M2 : My2Attribute absolute O;
  1781. begin
  1782. Obj:=FCtx.GetType(TypeInfo(TPropertyObject));
  1783. AssertEquals('Correct class type',TRttiInstanceType,Obj.ClassType);
  1784. Prop:=RttiData.GetProperty('ProtectedProperty');
  1785. AssertNotNull('Have property',Prop);
  1786. Attrs:=Prop.GetAttributes;
  1787. AssertNotNull('Have attribute data',Pointer(Attrs));
  1788. AssertEquals('attribute count',1,Length(Attrs));
  1789. AssertEquals('Attribute 1 name','My2Attribute',Attrs[0].ClassName);
  1790. O:=Attrs[0];
  1791. AssertNotNull('Attribute class ',O);
  1792. AssertEquals('Attribute class ',O.ClassType,My2Attribute);
  1793. AssertEquals('Attribute value ',3,M2.Int);
  1794. end;
  1795. procedure TTestClassExtendedRTTI.TestPublicPropertyAttributes;
  1796. var
  1797. Obj : TRttiObject;
  1798. RttiData : TRttiInstanceType absolute obj;
  1799. Attrs : TCustomAttributeArray;
  1800. Prop : TRttiProperty;
  1801. O : TCustomAttribute;
  1802. M3 : My3Attribute absolute O;
  1803. begin
  1804. Obj:=FCtx.GetType(TypeInfo(TPropertyObject));
  1805. AssertEquals('Correct class type',TRttiInstanceType,Obj.ClassType);
  1806. Prop:=RttiData.GetProperty('PublicProperty');
  1807. AssertNotNull('Have property',Prop);
  1808. Attrs:=Prop.GetAttributes;
  1809. AssertNotNull('Have attribute data',Pointer(Attrs));
  1810. AssertEquals('attribute count',1,Length(Attrs));
  1811. AssertEquals('Attribute 1 name','My3Attribute',Attrs[0].ClassName);
  1812. O:=Attrs[0];
  1813. AssertNotNull('Attribute class ',O);
  1814. AssertEquals('Attribute class ',O.ClassType,My3Attribute);
  1815. AssertEquals('Attribute value ',4,M3.Int);
  1816. end;
  1817. procedure TTestClassExtendedRTTI.TestPublishedPropertyAttributes;
  1818. var
  1819. Obj : TRttiObject;
  1820. RttiData : TRttiInstanceType absolute obj;
  1821. Attrs : TCustomAttributeArray;
  1822. Prop : TRttiProperty;
  1823. O : TCustomAttribute;
  1824. M3 : My3Attribute absolute O;
  1825. begin
  1826. Obj:=FCtx.GetType(TypeInfo(TPropertyObject));
  1827. AssertEquals('Correct class type',TRttiInstanceType,Obj.ClassType);
  1828. Prop:=RttiData.GetProperty('PublishedProperty');
  1829. AssertNotNull('Have property',Prop);
  1830. Attrs:=Prop.GetAttributes;
  1831. AssertNotNull('Have attribute data',Pointer(Attrs));
  1832. AssertEquals('attribute count',1,Length(Attrs));
  1833. AssertEquals('Attribute 1 name','My3Attribute',Attrs[0].ClassName);
  1834. O:=Attrs[0];
  1835. AssertNotNull('Attribute class ',O);
  1836. AssertEquals('Attribute class ',O.ClassType,My3Attribute);
  1837. AssertEquals('Attribute value ',5,M3.Int);
  1838. end;
  1839. procedure TTestClassExtendedRTTI.TestGetStaticProperty;
  1840. var
  1841. Obj : TRttiObject;
  1842. RttiData : TRttiInstanceType absolute obj;
  1843. Prop : TRttiProperty;
  1844. begin
  1845. Obj:=FCtx.GetType(TypeInfo(TTestAttr2Class));
  1846. TTestAttr2Class.StaticProp:=4539;
  1847. Prop:=rttiData.GetProperty('StaticProp');
  1848. AssertEquals('Class property is set or got incorrectly via methods', 4539, Prop.GetValue(nil).AsInteger);
  1849. end;
  1850. procedure TTestClassExtendedRTTI.TestSetStaticProperty;
  1851. var
  1852. Obj : TRttiObject;
  1853. RttiData : TRttiInstanceType absolute obj;
  1854. Prop : TRttiProperty;
  1855. begin
  1856. Obj:=FCtx.GetType(TypeInfo(TTestAttr2Class));
  1857. Prop:=rttiData.GetProperty('StaticProp');
  1858. // Write
  1859. Prop.SetValue(nil, 4539);
  1860. AssertEquals('Property correctly set',4539,TTestAttr2Class.StaticProp);
  1861. end;
  1862. { TTestRecordExtendedRTTI }
  1863. procedure TTestRecordExtendedRTTI.TestFields;
  1864. Var
  1865. A : TRttiFieldArray;
  1866. Obj : TRttiObject;
  1867. RttiData : TRttiRecordType absolute obj;
  1868. aCount : Integer;
  1869. begin
  1870. Obj:=FCtx.GetType(TypeInfo(TRecordFieldRTTI));
  1871. AssertEquals('Correct class type',TRttiRecordType,Obj.ClassType);
  1872. A:=RttiData.GetFields;
  1873. aCount:=Length(A);
  1874. AssertEquals('Record fields Count',4,aCount);
  1875. CheckField(0, A[0],'FRPrivateA',tkInteger,mvPrivate);
  1876. CheckField(1, A[1],'FRPrivateB',tkInteger,mvPrivate);
  1877. CheckField(4, A[2],'FRPublicA',tkInteger,mvPublic);
  1878. CheckField(5, A[3],'FRPublicB',tkInteger,mvPublic);
  1879. Obj:=FCtx.GetType(TypeInfo(TRecordFieldRTTIMixed));
  1880. AssertEquals('Correct class type',TRttiRecordType,Obj.ClassType);
  1881. A:=RttiData.GetFields;
  1882. aCount:=Length(A);
  1883. AssertEquals('Mixed record fields Count',4,aCount);
  1884. CheckField(0, A[0],'FRPrivateA',tkInteger,mvPrivate);
  1885. CheckField(1, A[1],'FRPrivateB',tkInteger,mvPrivate);
  1886. CheckField(4, A[2],'FRPublicA',tkInteger,mvPublic);
  1887. CheckField(5, A[3],'FRPublicB',tkInteger,mvPublic);
  1888. end;
  1889. procedure TTestRecordExtendedRTTI.TestProperties;
  1890. Var
  1891. A : TRttiPropertyArray;
  1892. Obj : TRttiObject;
  1893. RttiData : TRttiRecordType absolute obj;
  1894. aCount : Integer;
  1895. begin
  1896. // TRecordFieldRTTI
  1897. Obj:=FCtx.GetType(TypeInfo(TRecordFieldRTTI));
  1898. AssertEquals('Correct class type',TRttiRecordType,Obj.ClassType);
  1899. A:=RttiData.GetProperties;
  1900. aCount:=Length(A);
  1901. AssertEquals('Record property Count',4,aCount);
  1902. CheckProperty(0, A[0],'RPrivateA',tkInteger,mvPrivate);
  1903. CheckProperty(1, A[1],'RPrivateB',tkInteger,mvPrivate);
  1904. CheckProperty(2, A[2],'RPublicA',tkInteger,mvPublic);
  1905. CheckProperty(3, A[3],'RPublicB',tkInteger,mvPublic);
  1906. // TRecordFieldRTTIMixed
  1907. Obj:=FCtx.GetType(TypeInfo(TRecordFieldRTTIMixed));
  1908. AssertEquals('Correct class type',TRttiRecordType,Obj.ClassType);
  1909. A:=RttiData.GetProperties;
  1910. aCount:=Length(A);
  1911. AssertEquals('Record mixed property Count',4,aCount);
  1912. CheckProperty(0, A[0],'RPrivateA',tkInteger,mvPrivate);
  1913. CheckProperty(1, A[1],'RPrivateB',tkInteger,mvPrivate);
  1914. CheckProperty(2, A[2],'RPublicA',tkInteger,mvPublic);
  1915. CheckProperty(3, A[3],'RPublicB',tkInteger,mvPublic);
  1916. end;
  1917. procedure TTestRecordExtendedRTTI.TestDeclaredMethods;
  1918. Var
  1919. A : TRttiMethodArray;
  1920. Obj : TRttiObject;
  1921. RttiData : TRttiRecordType absolute obj;
  1922. aCount : Integer;
  1923. Parms : TRttiParameterArray;
  1924. begin
  1925. Obj:=FCtx.GetType(TypeInfo(TRecordMethodRTTI));
  1926. AssertEquals('Correct class type',TRttiRecordType,Obj.ClassType);
  1927. A:=RttiData.GetDeclaredMethods;
  1928. aCount:=Length(A);
  1929. AssertEquals('Method Full Count',4,aCount);
  1930. CheckMethod('Full',0, A[0],'PrivateMethodA',mvPrivate);
  1931. CheckMethod('Full',1, A[1],'PrivateMethodB',mvPrivate);
  1932. CheckMethod('Full',2, A[2],'PublicMethodA',mvPublic);
  1933. CheckMethod('Full',3, A[3],'PublicMethodB',mvPublic);
  1934. Parms:=A[3].GetParameters;
  1935. AssertEquals('Parameter length',1,Length(Parms));
  1936. AssertNotNull('Have Parameter',Parms[0]);
  1937. AssertEquals('Parameter name','I',Parms[0].Name);
  1938. end;
  1939. procedure TTestRecordExtendedRTTI.TestMethods;
  1940. Var
  1941. A : TRttiMethodArray;
  1942. Obj : TRttiObject;
  1943. RttiData : TRttiRecordType absolute obj;
  1944. aCount : Integer;
  1945. begin
  1946. Obj:=FCtx.GetType(TypeInfo(TRecordMethodRTTI));
  1947. AssertEquals('Correct class type',TRttiRecordType,Obj.ClassType);
  1948. A:=RttiData.GetDeclaredMethods;
  1949. aCount:=Length(A);
  1950. // Just check that the count is correct
  1951. AssertEquals('Method Full Count',4,aCount);
  1952. end;
  1953. Procedure TTestRecordExtendedRTTI.TestPrivateFieldAttributes;
  1954. var
  1955. Obj : TRttiObject;
  1956. RttiData : TRttiRecordType absolute obj;
  1957. Attrs : TCustomAttributeArray;
  1958. Fld : TRttiField;
  1959. O : TCustomAttribute;
  1960. M2 : My2Attribute absolute O;
  1961. begin
  1962. Obj:=FCtx.GetType(TypeInfo(TFieldRecord));
  1963. AssertEquals('Correct class type',TRttiRecordType,Obj.ClassType);
  1964. Fld:=RttiData.GetField('PrivateField');
  1965. AssertNotNull('Have field',Fld);
  1966. Attrs:=Fld.GetAttributes;
  1967. AssertNotNull('Have attribute data',Pointer(Attrs));
  1968. AssertEquals('attribute count',3,Length(Attrs));
  1969. AssertEquals('Attribute 1 name','WeakAttribute',Attrs[0].ClassName);
  1970. AssertEquals('Attribute 2 name','MyAttribute',Attrs[1].ClassName);
  1971. AssertEquals('Attribute 2 name','My2Attribute',Attrs[2].ClassName);
  1972. O:=Attrs[2];
  1973. AssertNotNull('Attribute class ',O);
  1974. AssertEquals('Attribute class ',O.ClassType,My2Attribute);
  1975. AssertEquals('Attribute value ',2,M2.Int);
  1976. end;
  1977. Procedure TTestRecordExtendedRTTI.TestPublicFieldAttributes;
  1978. var
  1979. Obj : TRttiObject;
  1980. RttiData : TRttiRecordType absolute obj;
  1981. Attrs : TCustomAttributeArray;
  1982. Fld : TRttiField;
  1983. O : TCustomAttribute;
  1984. M3 : My3Attribute absolute O;
  1985. aCount : Integer;
  1986. begin
  1987. Obj:=FCtx.GetType(TypeInfo(TFieldRecord));
  1988. AssertEquals('Correct class type',TRttiRecordType,Obj.ClassType);
  1989. aCount:=0;
  1990. For Fld in RttiData.GetFields do
  1991. if Fld.Visibility=mvPublic then
  1992. inc(aCount);
  1993. AssertEquals('Field count',3,aCount);
  1994. // PublicField
  1995. Fld:=RttiData.GetField('PublicField');
  1996. AssertNotNull('Have field',Fld);
  1997. Attrs:=Fld.GetAttributes;
  1998. AssertNotNull('Have attribute data',Pointer(Attrs));
  1999. AssertEquals('attribute count',1,Length(Attrs));
  2000. AssertEquals('Attribute 1 name','My3Attribute',Attrs[0].ClassName);
  2001. O:=Attrs[0];
  2002. AssertNotNull('Attribute class ',O);
  2003. AssertEquals('Attribute class ',O.ClassType,My3Attribute);
  2004. AssertEquals('Attribute value ',3,M3.Int);
  2005. // A
  2006. Fld:=RttiData.GetField('A');
  2007. AssertNotNull('A Have field',Fld);
  2008. Attrs:=Fld.GetAttributes;
  2009. AssertNotNull('A Have attribute data',Pointer(Attrs));
  2010. AssertEquals('A Attribute count',1,Length(Attrs));
  2011. AssertEquals('A Attribute 1 name','My3Attribute',Attrs[0].ClassName);
  2012. O:=Attrs[0];
  2013. AssertNotNull('A: Attribute class ',O);
  2014. AssertEquals('A: Attribute class ',O.ClassType,My3Attribute);
  2015. AssertEquals('A: Attribute value ',4,M3.Int);
  2016. // B
  2017. Fld:=RttiData.GetField('B');
  2018. AssertNotNull('B Have field',Fld);
  2019. Attrs:=Fld.GetAttributes;
  2020. AssertNotNull('B Have attribute data',Pointer(Attrs));
  2021. AssertEquals('A Attribute count',1,Length(Attrs));
  2022. AssertEquals('A Attribute 1 name','My3Attribute',Attrs[0].ClassName);
  2023. O:=Attrs[0];
  2024. AssertNotNull('B: Attribute class ',O);
  2025. AssertEquals('B: Attribute class ',O.ClassType,My3Attribute);
  2026. AssertEquals('B: Attribute value ',4,M3.Int);
  2027. end;
  2028. initialization
  2029. {$ifdef fpc}
  2030. RegisterTest(TTestRTTI);
  2031. RegisterTest(TTestClassExtendedRTTI);
  2032. RegisterTest(TTestRecordExtendedRTTI);
  2033. {$else fpc}
  2034. RegisterTest(TTestRTTI.Suite);
  2035. RegisterTest(TTestClassExtendedRTTI.suite);
  2036. RegisterTest(TTestRecordExtendedRTTI.Suite);
  2037. {$endif fpc}
  2038. end.