tests.rtti.pas 57 KB

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