tests.rtti.pas 70 KB

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