tests.rtti.pas 67 KB

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