tests.rtti.pas 69 KB

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