tests.rtti.pas 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580
  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. implementation
  68. uses
  69. Tests.Rtti.Util, tests.rtti.types;
  70. { Note: GetTypes currently only returns those types that had been acquired using
  71. GetType, so GetTypes itself can't be really tested currently }
  72. (*procedure TTestRTTI.GetTypes;
  73. var
  74. LContext: TRttiContext;
  75. LType: TRttiType;
  76. IsTestCaseClassFound: boolean;
  77. begin
  78. LContext := TRttiContext.Create;
  79. { Enumerate all types declared in the application }
  80. for LType in LContext.GetTypes() do
  81. begin
  82. if LType.Name='TTestRTTI' then
  83. IsTestCaseClassFound:=true;
  84. end;
  85. LContext.Free;
  86. CheckTrue(IsTestCaseClassFound, 'RTTI information does not contain class of testcase.');
  87. end;*)
  88. {$ifndef fpc}
  89. procedure TTestRTTI.Ignore(const aMsg: string);
  90. begin
  91. { empty }
  92. end;
  93. {$endif}
  94. procedure TTestRTTI.TestGetValueStringCastError;
  95. var
  96. ATestClass : TTestValueClass;
  97. c: TRttiContext;
  98. ARttiType: TRttiType;
  99. AValue: TValue;
  100. i: integer;
  101. HadException: boolean;
  102. begin
  103. c := TRttiContext.Create;
  104. try
  105. ATestClass := TTestValueClass.Create;
  106. ATestClass.AString := '12';
  107. try
  108. ARttiType := c.GetType(ATestClass.ClassInfo);
  109. AValue := ARttiType.GetProperty('astring').GetValue(ATestClass);
  110. HadException := false;
  111. try
  112. i := AValue.AsInteger;
  113. except
  114. on E: Exception do
  115. if E.ClassType=EInvalidCast then
  116. HadException := true;
  117. end;
  118. Check(HadException, 'No or invalid exception on invalid cast');
  119. finally
  120. AtestClass.Free;
  121. end;
  122. finally
  123. c.Free;
  124. end;
  125. end;
  126. procedure TTestRTTI.TestGetIsReadable;
  127. var
  128. c: TRttiContext;
  129. ARttiType: TRttiType;
  130. AProperty: TRttiProperty;
  131. begin
  132. c := TRttiContext.Create;
  133. try
  134. ARttiType := c.GetType(TTestValueClass);
  135. AProperty := ARttiType.GetProperty('aBoolean');
  136. CheckEquals(AProperty.IsReadable, true);
  137. AProperty := ARttiType.GetProperty('aGetBoolean');
  138. CheckEquals(AProperty.IsReadable, true);
  139. AProperty := ARttiType.GetProperty('aWriteOnly');
  140. CheckEquals(AProperty.IsReadable, False);
  141. finally
  142. c.Free;
  143. end;
  144. end;
  145. procedure TTestRTTI.TestIsWritable;
  146. var
  147. c: TRttiContext;
  148. ARttiType: TRttiType;
  149. AProperty: TRttiProperty;
  150. begin
  151. c := TRttiContext.Create;
  152. try
  153. ARttiType := c.GetType(TTestValueClass);
  154. AProperty := ARttiType.GetProperty('aBoolean');
  155. CheckEquals(AProperty.IsWritable, true);
  156. AProperty := ARttiType.GetProperty('aGetBoolean');
  157. CheckEquals(AProperty.IsWritable, false);
  158. AProperty := ARttiType.GetProperty('aWriteOnly');
  159. CheckEquals(AProperty.IsWritable, True);
  160. finally
  161. c.Free;
  162. end;
  163. end;
  164. procedure TTestRTTI.TestGetAttribute;
  165. // TMyAnnotatedClass
  166. // TMyAttribute
  167. var
  168. c: TRttiContext;
  169. aType: TRttiType;
  170. aClass : TMyAnnotatedClass;
  171. custAttr : TCustomAttribute;
  172. myAttr : TMyAttribute absolute custattr;
  173. begin
  174. aType:=nil;
  175. custAttr:=Nil;
  176. c := TRttiContext.Create;
  177. try
  178. aClass:=TMyAnnotatedClass.Create;
  179. aType := c.GetType(aClass.ClassInfo);
  180. custAttr:=aType.GetAttribute(TMyAttribute);
  181. CheckEquals(custAttr.ClassType,TMyAttribute,'Correct class');
  182. CheckEquals('something',MyAttr.value,'Correct value');
  183. finally
  184. aClass.Free;
  185. // custAttr.Free;
  186. C.Free;
  187. end;
  188. end;
  189. procedure TTestRTTI.TestPropGetValueBoolean;
  190. var
  191. ATestClass : TTestValueClass;
  192. c: TRttiContext;
  193. ARttiType: TRttiType;
  194. AProperty: TRttiProperty;
  195. AValue: TValue;
  196. begin
  197. c := TRttiContext.Create;
  198. try
  199. ATestClass := TTestValueClass.Create;
  200. ATestClass.ABoolean := true;
  201. try
  202. ARttiType := c.GetType(ATestClass.ClassInfo);
  203. Check(assigned(ARttiType));
  204. AProperty := ARttiType.GetProperty('aBoolean');
  205. AValue := AProperty.GetValue(ATestClass);
  206. CheckEquals(true,AValue.AsBoolean);
  207. ATestClass.ABoolean := false;
  208. CheckEquals(true, AValue.AsBoolean);
  209. CheckEquals('True', AValue.ToString);
  210. CheckEquals(True, AValue.IsOrdinal);
  211. CheckEquals(1, AValue.AsOrdinal);
  212. finally
  213. AtestClass.Free;
  214. end;
  215. CheckEquals(True,AValue.AsBoolean);
  216. finally
  217. c.Free;
  218. end;
  219. end;
  220. procedure TTestRTTI.TestPropGetValueShortString;
  221. var
  222. ATestClass : TTestValueClass;
  223. c: TRttiContext;
  224. ARttiType: TRttiType;
  225. AProperty: TRttiProperty;
  226. AValue: TValue;
  227. begin
  228. c := TRttiContext.Create;
  229. try
  230. ATestClass := TTestValueClass.Create;
  231. ATestClass.AShortString := 'Hello World';
  232. try
  233. ARttiType := c.GetType(ATestClass.ClassInfo);
  234. Check(assigned(ARttiType));
  235. AProperty := ARttiType.GetProperty('aShortString');
  236. AValue := AProperty.GetValue(ATestClass);
  237. CheckEquals('Hello World',AValue.AsString);
  238. ATestClass.AShortString := 'Foobar';
  239. CheckEquals('Hello World', AValue.AsString);
  240. CheckEquals(False, AValue.IsOrdinal);
  241. CheckEquals(False, AValue.IsObject);
  242. CheckEquals(False, AValue.IsArray);
  243. CheckEquals(False, AValue.IsClass);
  244. finally
  245. AtestClass.Free;
  246. end;
  247. CheckEquals('Hello World',AValue.AsString);
  248. finally
  249. c.Free;
  250. end;
  251. end;
  252. procedure TTestRTTI.TestPropGetValueInteger;
  253. var
  254. ATestClass : TTestValueClass;
  255. c: TRttiContext;
  256. ARttiType: TRttiType;
  257. AProperty: TRttiProperty;
  258. AValue: TValue;
  259. begin
  260. c := TRttiContext.Create;
  261. try
  262. ATestClass := TTestValueClass.Create;
  263. ATestClass.AInteger := 472349;
  264. try
  265. ARttiType := c.GetType(ATestClass.ClassInfo);
  266. Check(assigned(ARttiType));
  267. AProperty := ARttiType.GetProperty('ainteger');
  268. AValue := AProperty.GetValue(ATestClass);
  269. CheckEquals(472349,AValue.AsInteger);
  270. ATestClass.AInteger := 12;
  271. CheckEquals(472349, AValue.AsInteger);
  272. CheckEquals('472349', AValue.ToString);
  273. CheckEquals(True, AValue.IsOrdinal);
  274. finally
  275. AtestClass.Free;
  276. end;
  277. CheckEquals(472349,AValue.AsInteger);
  278. finally
  279. c.Free;
  280. end;
  281. end;
  282. procedure TTestRTTI.TestPropGetValueString;
  283. var
  284. ATestClass : TTestValueClass;
  285. c: TRttiContext;
  286. ARttiType: TRttiType;
  287. AProperty: TRttiProperty;
  288. AValue: TValue;
  289. i: int64;
  290. begin
  291. c := TRttiContext.Create;
  292. try
  293. ATestClass := TTestValueClass.Create;
  294. ATestClass.AString := 'Hello World';
  295. try
  296. ARttiType := c.GetType(ATestClass.ClassInfo);
  297. Check(assigned(ARttiType));
  298. AProperty := ARttiType.GetProperty('astring');
  299. AValue := AProperty.GetValue(ATestClass);
  300. CheckEquals('Hello World',AValue.AsString);
  301. ATestClass.AString := 'Goodbye World';
  302. CheckEquals('Hello World',AValue.AsString);
  303. CheckEquals('Hello World',AValue.ToString);
  304. Check(TypeInfo(string)=AValue.TypeInfo);
  305. Check(AValue.TypeData=GetTypeData(AValue.TypeInfo));
  306. Check(AValue.IsEmpty=false);
  307. Check(AValue.IsObject=false);
  308. Check(AValue.IsClass=false);
  309. CheckEquals(AValue.IsOrdinal, false);
  310. CheckEquals(AValue.TryAsOrdinal(i), false);
  311. CheckEquals(AValue.IsType(TypeInfo(string)), true);
  312. CheckEquals(AValue.IsType(TypeInfo(integer)), false);
  313. CheckEquals(AValue.IsArray, false);
  314. finally
  315. AtestClass.Free;
  316. end;
  317. CheckEquals('Hello World',AValue.AsString);
  318. finally
  319. c.Free;
  320. end;
  321. end;
  322. procedure TTestRTTI.TestPropGetValueProcBoolean;
  323. var
  324. ATestClass : TTestValueClass;
  325. c: TRttiContext;
  326. ARttiType: TRttiType;
  327. AProperty: TRttiProperty;
  328. AValue: TValue;
  329. begin
  330. c := TRttiContext.Create;
  331. try
  332. ATestClass := TTestValueClass.Create;
  333. ATestClass.ABoolean := true;
  334. try
  335. ARttiType := c.GetType(ATestClass.ClassInfo);
  336. Check(assigned(ARttiType));
  337. AProperty := ARttiType.GetProperty('aGetBoolean');
  338. AValue := AProperty.GetValue(ATestClass);
  339. CheckEquals(true,AValue.AsBoolean);
  340. finally
  341. AtestClass.Free;
  342. end;
  343. CheckEquals(True,AValue.AsBoolean);
  344. finally
  345. c.Free;
  346. end;
  347. end;
  348. procedure TTestRTTI.TestPropGetValueProcShortString;
  349. var
  350. ATestClass : TTestValueClass;
  351. c: TRttiContext;
  352. ARttiType: TRttiType;
  353. AProperty: TRttiProperty;
  354. AValue: TValue;
  355. begin
  356. c := TRttiContext.Create;
  357. try
  358. ATestClass := TTestValueClass.Create;
  359. ATestClass.AShortString := 'Hello World';
  360. try
  361. ARttiType := c.GetType(ATestClass.ClassInfo);
  362. Check(assigned(ARttiType));
  363. AProperty := ARttiType.GetProperty('aGetShortString');
  364. AValue := AProperty.GetValue(ATestClass);
  365. CheckEquals('Hello World',AValue.AsString);
  366. finally
  367. AtestClass.Free;
  368. end;
  369. CheckEquals('Hello World',AValue.AsString);
  370. finally
  371. c.Free;
  372. end;
  373. end;
  374. procedure TTestRTTI.TestPropGetValueObject;
  375. var
  376. ATestClass : TTestValueClass;
  377. c: TRttiContext;
  378. ARttiType: TRttiType;
  379. AProperty: TRttiProperty;
  380. AValue: TValue;
  381. O: TObject;
  382. begin
  383. c := TRttiContext.Create;
  384. O := TObject.Create;
  385. try
  386. ATestClass := TTestValueClass.Create;
  387. ATestClass.AObject := O;
  388. try
  389. ARttiType := c.GetType(ATestClass.ClassInfo);
  390. Check(assigned(ARttiType));
  391. AProperty := ARttiType.GetProperty('AObject');
  392. AValue := AProperty.GetValue(ATestClass);
  393. CheckEquals(O.GetHashCode, AValue.AsObject.GetHashCode);
  394. finally
  395. AtestClass.Free;
  396. end;
  397. CheckEquals(O.GetHashCode, AValue.AsObject.GetHashCode);
  398. finally
  399. c.Free;
  400. O.Free;
  401. end;
  402. end;
  403. procedure TTestRTTI.TestPropGetValueInterface;
  404. var
  405. ATestClass : TTestValueClass;
  406. c: TRttiContext;
  407. ARttiType: TRttiType;
  408. AProperty: TRttiProperty;
  409. AValue: TValue;
  410. i: IInterface;
  411. begin
  412. c := TRttiContext.Create;
  413. i := TInterfacedObject.Create;
  414. try
  415. ATestClass := TTestValueClass.Create;
  416. ATestClass.AUnknown := i;
  417. try
  418. ARttiType := c.GetType(ATestClass.ClassInfo);
  419. Check(assigned(ARttiType));
  420. AProperty := ARttiType.GetProperty('AUnknown');
  421. AValue := AProperty.GetValue(ATestClass);
  422. Check(i = AValue.AsInterface);
  423. finally
  424. AtestClass.Free;
  425. end;
  426. Check(i = AValue.AsInterface);
  427. finally
  428. c.Free;
  429. end;
  430. end;
  431. procedure TTestRTTI.TestPropGetValueFloat;
  432. var
  433. ATestClass : TTestValueClass;
  434. c: TRttiContext;
  435. ARttiType: TRttiType;
  436. AProperty: TRttiProperty;
  437. AValueS, AValueD, AValueE, AValueC, AValueCm: TValue;
  438. begin
  439. c := TRttiContext.Create;
  440. try
  441. ATestClass := TTestValueClass.Create;
  442. ATestClass.ASingle := 1.1;
  443. ATestClass.ADouble := 2.2;
  444. ATestClass.AExtended := 3.3;
  445. ATestClass.ACurrency := 4;
  446. ATestClass.AComp := 5;
  447. try
  448. ARttiType := c.GetType(ATestClass.ClassInfo);
  449. Check(assigned(ARttiType));
  450. AProperty := ARttiType.GetProperty('ASingle');
  451. AValueS := AProperty.GetValue(ATestClass);
  452. CheckEquals(1.1, AValueS.AsExtended, 0.001);
  453. AProperty := ARttiType.GetProperty('ADouble');
  454. AValueD := AProperty.GetValue(ATestClass);
  455. CheckEquals(2.2, AValueD.AsExtended, 0.001);
  456. AProperty := ARttiType.GetProperty('AExtended');
  457. AValueE := AProperty.GetValue(ATestClass);
  458. CheckEquals(3.3, AValueE.AsExtended, 0.001);
  459. AProperty := ARttiType.GetProperty('ACurrency');
  460. AValueC := AProperty.GetValue(ATestClass);
  461. CheckEquals(4.0, AValueC.AsExtended, 0.001);
  462. AProperty := ARttiType.GetProperty('AComp');
  463. AValueCm := AProperty.GetValue(ATestClass);
  464. CheckEquals(5.0, AValueCm.AsExtended, 0.001);
  465. finally
  466. AtestClass.Free;
  467. end;
  468. CheckEquals(1.1, AValueS.AsExtended, 0.001);
  469. CheckEquals(2.2, AValueD.AsExtended, 0.001);
  470. CheckEquals(3.3, AValueE.AsExtended, 0.001);
  471. CheckEquals(4.0, AValueC.AsExtended, 0.001);
  472. CheckEquals(5.0, AValueCm.AsExtended, 0.001);
  473. finally
  474. c.Free;
  475. end;
  476. end;
  477. procedure TTestRTTI.TestPropGetValueDynArray;
  478. var
  479. ATestClass : TTestValueClass;
  480. c: TRttiContext;
  481. ARttiType: TRttiType;
  482. AProperty: TRttiProperty;
  483. AValue: TValue;
  484. A: TTestDynArray;
  485. begin
  486. c := TRttiContext.Create;
  487. A := [1, 2, 3, 4];
  488. try
  489. ATestClass := TTestValueClass.Create;
  490. ATestClass.AArray := A;
  491. try
  492. ARttiType := c.GetType(ATestClass.ClassInfo);
  493. Check(assigned(ARttiType));
  494. AProperty := ARttiType.GetProperty('AArray');
  495. AValue := AProperty.GetValue(ATestClass);
  496. CheckEquals(A[0], AValue.GetArrayElement(0).AsInteger);
  497. CheckEquals(A[1], AValue.GetArrayElement(1).AsInteger);
  498. CheckEquals(A[2], AValue.GetArrayElement(2).AsInteger);
  499. CheckEquals(A[3], AValue.GetArrayElement(3).AsInteger);
  500. finally
  501. AtestClass.Free;
  502. end;
  503. finally
  504. c.Free;
  505. end;
  506. end;
  507. procedure TTestRTTI.TestPropGetValueEnumeration;
  508. var
  509. ATestClass : TTestValueClass;
  510. c: TRttiContext;
  511. ARttiType: TRttiType;
  512. AProperty: TRttiProperty;
  513. AValue: TValue;
  514. begin
  515. c := TRttiContext.Create;
  516. try
  517. ATestClass := TTestValueClass.Create;
  518. ATestClass.AEnumeration := en3;
  519. try
  520. ARttiType := c.GetType(ATestClass.ClassInfo);
  521. Check(assigned(ARttiType));
  522. AProperty := ARttiType.GetProperty('AEnumeration');
  523. AValue := AProperty.GetValue(ATestClass);
  524. CheckEquals(Ord(en3),AValue.AsOrdinal);
  525. ATestClass.AEnumeration := en1;
  526. CheckEquals(Ord(en3), AValue.AsOrdinal);
  527. CheckEquals('en3', AValue.ToString);
  528. CheckEquals(True, AValue.IsOrdinal);
  529. finally
  530. AtestClass.Free;
  531. end;
  532. CheckEquals(Ord(en3),AValue.AsOrdinal);
  533. finally
  534. c.Free;
  535. end;
  536. end;
  537. procedure TTestRTTI.TestPropGetValueChars;
  538. var
  539. ATestClass : TTestValueClass;
  540. c: TRttiContext;
  541. ARttiType: TRttiType;
  542. AProperty: TRttiProperty;
  543. AValueC, AValueW: TValue;
  544. begin
  545. c := TRttiContext.Create;
  546. try
  547. ATestClass := TTestValueClass.Create;
  548. ATestClass.AChar := 'C';
  549. ATestClass.AWideChar := 'W';
  550. try
  551. ARttiType := c.GetType(ATestClass.ClassInfo);
  552. Check(assigned(ARttiType));
  553. AProperty := ARttiType.GetProperty('AChar');
  554. AValueC := AProperty.GetValue(ATestClass);
  555. CheckEquals('C',AValueC.AsAnsiChar);
  556. ATestClass.AChar := 'N';
  557. CheckEquals('C', AValueC.AsAnsiChar);
  558. CheckEquals('C', AValueC.ToString);
  559. CheckEquals(True, AValueC.IsOrdinal);
  560. AProperty := ARttiType.GetProperty('AWideChar');
  561. AValueW := AProperty.GetValue(ATestClass);
  562. CheckEquals('W',AValueW.AsWideChar);
  563. ATestClass.AWideChar := 'Z';
  564. CheckEquals('W', AValueW.AsWideChar);
  565. CheckEquals('W', AValueW.ToString);
  566. CheckEquals(True, AValueW.IsOrdinal);
  567. finally
  568. AtestClass.Free;
  569. end;
  570. CheckEquals('C',AValueC.AsAnsiChar);
  571. CheckEquals('W',AValueW.AsWideChar);
  572. finally
  573. c.Free;
  574. end;
  575. end;
  576. procedure TTestRTTI.TestPropSetValueString;
  577. var
  578. ATestClass : TTestValueClass;
  579. c: TRttiContext;
  580. ARttiType: TRttiType;
  581. AProperty: TRttiProperty;
  582. AValue: TValue;
  583. s: string;
  584. begin
  585. c := TRttiContext.Create;
  586. try
  587. ATestClass := TTestValueClass.Create;
  588. try
  589. ARttiType := c.GetType(ATestClass.ClassInfo);
  590. AProperty := ARttiType.GetProperty('astring');
  591. s := 'ipse lorem or something like that';
  592. TValue.Make(@s, TypeInfo(string), AValue);
  593. AProperty.SetValue(ATestClass, AValue);
  594. CheckEquals(ATestClass.AString, s);
  595. s := 'Another string';
  596. CheckEquals(ATestClass.AString, 'ipse lorem or something like that');
  597. finally
  598. AtestClass.Free;
  599. end;
  600. finally
  601. c.Free;
  602. end;
  603. end;
  604. procedure TTestRTTI.TestPropSetValueInteger;
  605. var
  606. ATestClass : TTestValueClass;
  607. c: TRttiContext;
  608. ARttiType: TRttiType;
  609. AProperty: TRttiProperty;
  610. AValue: TValue;
  611. i: integer;
  612. begin
  613. c := TRttiContext.Create;
  614. try
  615. ATestClass := TTestValueClass.Create;
  616. try
  617. ARttiType := c.GetType(ATestClass.ClassInfo);
  618. AProperty := ARttiType.GetProperty('aInteger');
  619. i := -43573;
  620. TValue.Make(@i, TypeInfo(Integer), AValue);
  621. AProperty.SetValue(ATestClass, AValue);
  622. CheckEquals(ATestClass.AInteger, i);
  623. i := 1;
  624. CheckEquals(ATestClass.AInteger, -43573);
  625. finally
  626. AtestClass.Free;
  627. end;
  628. finally
  629. c.Free;
  630. end;
  631. end;
  632. procedure TTestRTTI.TestPropSetValueBoolean;
  633. var
  634. ATestClass : TTestValueClass;
  635. c: TRttiContext;
  636. ARttiType: TRttiType;
  637. AProperty: TRttiProperty;
  638. AValue: TValue;
  639. b: boolean;
  640. begin
  641. c := TRttiContext.Create;
  642. try
  643. ATestClass := TTestValueClass.Create;
  644. try
  645. ARttiType := c.GetType(ATestClass.ClassInfo);
  646. AProperty := ARttiType.GetProperty('aboolean');
  647. b := true;
  648. TValue.Make(@b, TypeInfo(Boolean), AValue);
  649. AProperty.SetValue(ATestClass, AValue);
  650. CheckEquals(ATestClass.ABoolean, b);
  651. b := false;
  652. CheckEquals(ATestClass.ABoolean, true);
  653. TValue.Make(@b, TypeInfo(Boolean), AValue);
  654. AProperty.SetValue(ATestClass, AValue);
  655. CheckEquals(ATestClass.ABoolean, false);
  656. finally
  657. AtestClass.Free;
  658. end;
  659. finally
  660. c.Free;
  661. end;
  662. end;
  663. procedure TTestRTTI.TestPropSetValueShortString;
  664. var
  665. ATestClass : TTestValueClass;
  666. c: TRttiContext;
  667. ARttiType: TRttiType;
  668. AProperty: TRttiProperty;
  669. AValue: TValue;
  670. s: string;
  671. ss: ShortString;
  672. begin
  673. c := TRttiContext.Create;
  674. try
  675. ATestClass := TTestValueClass.Create;
  676. try
  677. ARttiType := c.GetType(ATestClass.ClassInfo);
  678. AProperty := ARttiType.GetProperty('aShortString');
  679. s := 'ipse lorem or something like that';
  680. TValue.Make(@s, TypeInfo(String), AValue);
  681. AProperty.SetValue(ATestClass, AValue);
  682. CheckEquals(ATestClass.AShortString, s);
  683. s := 'Another string';
  684. CheckEquals(ATestClass.AShortString, 'ipse lorem or something like that');
  685. ss := 'Hello World';
  686. TValue.Make(@ss, TypeInfo(ShortString), AValue);
  687. AProperty.SetValue(ATestClass, AValue);
  688. CheckEquals(ATestClass.AShortString, ss);
  689. ss := 'Foobar';
  690. CheckEquals(ATestClass.AShortString, 'Hello World');
  691. AProperty.SetValue(ATestClass, 'Another string');
  692. CheckEquals(ATestClass.AShortString, 'Another string');
  693. finally
  694. AtestClass.Free;
  695. end;
  696. finally
  697. c.Free;
  698. end;
  699. end;
  700. procedure TTestRTTI.TestPropSetValueObject;
  701. var
  702. ATestClass : TTestValueClass;
  703. c: TRttiContext;
  704. ARttiType: TRttiType;
  705. AProperty: TRttiProperty;
  706. AValue: TValue;
  707. O: TObject;
  708. TypeInfo: PTypeInfo;
  709. begin
  710. c := TRttiContext.Create;
  711. try
  712. ATestClass := TTestValueClass.Create;
  713. try
  714. ARttiType := c.GetType(ATestClass.ClassInfo);
  715. AProperty := ARttiType.GetProperty('AObject');
  716. TypeInfo := GetPropInfo(ATestClass, 'AObject')^.PropType{$ifndef fpc}^{$endif};
  717. O := TPersistent.Create;
  718. TValue.Make(@O, TypeInfo, AValue);
  719. AProperty.SetValue(ATestClass, AValue);
  720. CheckEquals(ATestClass.AObject.GetHashCode, O.GetHashCode);
  721. O.Free;
  722. O := TPersistent.Create;
  723. AProperty.SetValue(ATestClass, O);
  724. CheckEquals(ATestClass.AObject.GetHashCode, O.GetHashCode);
  725. O.Free;
  726. finally
  727. AtestClass.Free;
  728. end;
  729. finally
  730. c.Free;
  731. end;
  732. end;
  733. procedure TTestRTTI.TestPropSetValueInterface;
  734. var
  735. ATestClass : TTestValueClass;
  736. c: TRttiContext;
  737. ARttiType: TRttiType;
  738. AProperty: TRttiProperty;
  739. AValue: TValue;
  740. TypeInfo: PTypeInfo;
  741. i: IInterface;
  742. begin
  743. c := TRttiContext.Create;
  744. try
  745. ATestClass := TTestValueClass.Create;
  746. try
  747. ARttiType := c.GetType(ATestClass.ClassInfo);
  748. AProperty := ARttiType.GetProperty('AUnknown');
  749. TypeInfo := GetPropInfo(ATestClass, 'AUnknown')^.PropType{$ifndef fpc}^{$endif};
  750. i := TInterfacedObject.Create;
  751. TValue.Make(@i, TypeInfo, AValue);
  752. AProperty.SetValue(ATestClass, AValue);
  753. Check(ATestClass.AUnknown = i);
  754. {$ifdef fpc}
  755. { Delphi does not provide an implicit assignment overload for IUnknown }
  756. i := TInterfacedObject.Create;
  757. AProperty.SetValue(ATestClass, i);
  758. Check(ATestClass.AUnknown = i);
  759. {$endif}
  760. finally
  761. AtestClass.Free;
  762. end;
  763. finally
  764. c.Free;
  765. end;
  766. end;
  767. procedure TTestRTTI.TestPropSetValueFloat;
  768. var
  769. ATestClass : TTestValueClass;
  770. c: TRttiContext;
  771. ARttiType: TRttiType;
  772. AProperty: TRttiProperty;
  773. AValue: TValue;
  774. TypeInfo: PTypeInfo;
  775. S: Single;
  776. D: Double;
  777. E: Extended;
  778. Cur: Currency;
  779. Cmp: Comp;
  780. begin
  781. c := TRttiContext.Create;
  782. try
  783. ATestClass := TTestValueClass.Create;
  784. try
  785. ARttiType := c.GetType(ATestClass.ClassInfo);
  786. AProperty := ARttiType.GetProperty('ASingle');
  787. TypeInfo := GetPropInfo(ATestClass, 'ASingle')^.PropType{$ifndef fpc}^{$endif};
  788. S := 1.1;
  789. TValue.Make(@S, TypeInfo, AValue);
  790. AProperty.SetValue(ATestClass, AValue);
  791. CheckEquals(S, ATestClass.ASingle, 0.001);
  792. S := 1.2;
  793. AProperty.SetValue(ATestClass, S);
  794. CheckEquals(S, ATestClass.ASingle, 0.001);
  795. AProperty := ARttiType.GetProperty('ADouble');
  796. TypeInfo := GetPropInfo(ATestClass, 'ADouble')^.PropType{$ifndef fpc}^{$endif};
  797. D := 2.1;
  798. TValue.Make(@D, TypeInfo, AValue);
  799. AProperty.SetValue(ATestClass, AValue);
  800. CheckEquals(D, ATestClass.ADouble, 0.001);
  801. D := 2.2;
  802. AProperty.SetValue(ATestClass, D);
  803. CheckEquals(D, ATestClass.ADouble, 0.001);
  804. AProperty := ARttiType.GetProperty('AExtended');
  805. TypeInfo := GetPropInfo(ATestClass, 'AExtended')^.PropType{$ifndef fpc}^{$endif};
  806. E := 3.1;
  807. TValue.Make(@E, TypeInfo, AValue);
  808. AProperty.SetValue(ATestClass, AValue);
  809. CheckEquals(E, ATestClass.AExtended, 0.001);
  810. E := 3.2;
  811. AProperty.SetValue(ATestClass, E);
  812. CheckEquals(E, ATestClass.AExtended, 0.001);
  813. AProperty := ARttiType.GetProperty('ACurrency');
  814. TypeInfo := GetPropInfo(ATestClass, 'ACurrency')^.PropType{$ifndef fpc}^{$endif};
  815. Cur := 40;
  816. TValue.Make(@Cur, TypeInfo, AValue);
  817. AProperty.SetValue(ATestClass, AValue);
  818. CheckEquals(Cur, ATestClass.ACurrency, 0.001);
  819. Cur := 41;
  820. AProperty.SetValue(ATestClass, Cur);
  821. CheckEquals(Cur, ATestClass.ACurrency, 0.001);
  822. AProperty := ARttiType.GetProperty('AComp');
  823. TypeInfo := GetPropInfo(ATestClass, 'AComp')^.PropType{$ifndef fpc}^{$endif};
  824. Cmp := 50;
  825. TValue.Make(@Cmp, TypeInfo, AValue);
  826. AProperty.SetValue(ATestClass, AValue);
  827. CheckEquals(Cmp, ATestClass.AComp, 0.001);
  828. Cmp := 51;
  829. AProperty.SetValue(ATestClass, Cmp);
  830. CheckEquals(Cmp, ATestClass.AComp, 0.001);
  831. finally
  832. AtestClass.Free;
  833. end;
  834. finally
  835. c.Free;
  836. end;
  837. end;
  838. procedure TTestRTTI.TestPropSetValueDynArray;
  839. var
  840. ATestClass : TTestValueClass;
  841. c: TRttiContext;
  842. ARttiType: TRttiType;
  843. AProperty: TRttiProperty;
  844. AValue: TValue;
  845. A: TTestDynArray;
  846. TypeInfo: PTypeInfo;
  847. i: Integer;
  848. begin
  849. c := TRttiContext.Create;
  850. try
  851. ATestClass := TTestValueClass.Create;
  852. try
  853. ARttiType := c.GetType(ATestClass.ClassInfo);
  854. AProperty := ARttiType.GetProperty('AArray');
  855. TypeInfo := GetPropInfo(ATestClass, 'AArray')^.PropType{$ifndef fpc}^{$endif};
  856. A := [1, 2, 3, 4, 5];
  857. TValue.Make(@A, TypeInfo, AValue);
  858. AProperty.SetValue(ATestClass, AValue);
  859. for i := 0 to High(A) do
  860. CheckEquals(A[i], ATestClass.AArray[i]);
  861. finally
  862. AtestClass.Free;
  863. end;
  864. finally
  865. c.Free;
  866. end;
  867. end;
  868. procedure TTestRTTI.TestPropSetValueEnumeration;
  869. var
  870. ATestClass : TTestValueClass;
  871. c: TRttiContext;
  872. ARttiType: TRttiType;
  873. AProperty: TRttiProperty;
  874. AValue: TValue;
  875. E: TTestEnumeration;
  876. begin
  877. c := TRttiContext.Create;
  878. try
  879. ATestClass := TTestValueClass.Create;
  880. try
  881. ARttiType := c.GetType(ATestClass.ClassInfo);
  882. AProperty := ARttiType.GetProperty('AEnumeration');
  883. E := en2;
  884. TValue.Make(@E, TypeInfo(TTestEnumeration), AValue);
  885. AProperty.SetValue(ATestClass, AValue);
  886. CheckEquals(Ord(E), Ord(ATestClass.AEnumeration));
  887. finally
  888. AtestClass.Free;
  889. end;
  890. finally
  891. c.Free;
  892. end;
  893. end;
  894. procedure TTestRTTI.TestPropSetValueChars;
  895. var
  896. ATestClass : TTestValueClass;
  897. c: TRttiContext;
  898. ARttiType: TRttiType;
  899. AProperty: TRttiProperty;
  900. AValueC, AValueW: TValue;
  901. begin
  902. c := TRttiContext.Create;
  903. try
  904. ATestClass := TTestValueClass.Create;
  905. ATestClass.AChar := 'C';
  906. ATestClass.AWideChar := 'W';
  907. try
  908. ARttiType := c.GetType(ATestClass.ClassInfo);
  909. Check(assigned(ARttiType));
  910. AProperty := ARttiType.GetProperty('AChar');
  911. AValueC := AProperty.GetValue(ATestClass);
  912. CheckEquals('C', AValueC.AsAnsiChar);
  913. AProperty := ARttiType.GetProperty('AWideChar');
  914. AValueW := AProperty.GetValue(ATestClass);
  915. CheckEquals('W', AValueW.AsWideChar);
  916. finally
  917. AtestClass.Free;
  918. end;
  919. CheckEquals('C', AValueC.AsAnsiChar);
  920. CheckEquals('W', AValueW.AsWideChar);
  921. finally
  922. c.Free;
  923. end;
  924. end;
  925. procedure TTestRTTI.TestPropGetValueProcInteger;
  926. var
  927. ATestClass : TTestValueClass;
  928. c: TRttiContext;
  929. ARttiType: TRttiType;
  930. AProperty: TRttiProperty;
  931. AValue: TValue;
  932. begin
  933. c := TRttiContext.Create;
  934. try
  935. ATestClass := TTestValueClass.Create;
  936. ATestClass.AInteger := 472349;
  937. try
  938. ARttiType := c.GetType(ATestClass.ClassInfo);
  939. Check(assigned(ARttiType));
  940. AProperty := ARttiType.GetProperty('agetinteger');
  941. AValue := AProperty.GetValue(ATestClass);
  942. CheckEquals(472349,AValue.AsInteger);
  943. finally
  944. AtestClass.Free;
  945. end;
  946. CheckEquals(472349,AValue.AsInteger);
  947. finally
  948. c.Free;
  949. end;
  950. end;
  951. procedure TTestRTTI.TestPropGetValueProcString;
  952. var
  953. ATestClass : TTestValueClass;
  954. c: TRttiContext;
  955. ARttiType: TRttiType;
  956. AProperty: TRttiProperty;
  957. AValue: TValue;
  958. begin
  959. c := TRttiContext.Create;
  960. try
  961. ATestClass := TTestValueClass.Create;
  962. ATestClass.AString := 'Hello World';
  963. try
  964. ARttiType := c.GetType(ATestClass.ClassInfo);
  965. Check(assigned(ARttiType));
  966. AProperty := ARttiType.GetProperty('agetstring');
  967. AValue := AProperty.GetValue(ATestClass);
  968. CheckEquals('Hello World',AValue.AsString);
  969. finally
  970. AtestClass.Free;
  971. end;
  972. CheckEquals('Hello World',AValue.AsString);
  973. finally
  974. c.Free;
  975. end;
  976. end;
  977. procedure TTestRTTI.TestTRttiTypeProperties;
  978. var
  979. c: TRttiContext;
  980. ARttiType: TRttiType;
  981. begin
  982. c := TRttiContext.Create;
  983. try
  984. ARttiType := c.GetType(TTestValueClass);
  985. Check(assigned(ARttiType));
  986. CheckEquals(ARttiType.Name,'TTestValueClass');
  987. Check(ARttiType.TypeKind=tkClass);
  988. // CheckEquals(ARttiType.IsPublicType,false);
  989. CheckEquals(ARttiType.TypeSize,SizeOf(TObject));
  990. CheckEquals(ARttiType.IsManaged,false);
  991. CheckEquals(ARttiType.BaseType.classname,'TRttiInstanceType');
  992. CheckEquals(ARttiType.IsInstance,True);
  993. CheckEquals(ARttiType.AsInstance.DeclaringUnitName,'tests.rtti.types');
  994. Check(ARttiType.BaseType.Name='TObject');
  995. Check(ARttiType.AsInstance.BaseType.Name='TObject');
  996. CheckEquals(ARttiType.IsOrdinal,False);
  997. CheckEquals(ARttiType.IsRecord,False);
  998. CheckEquals(ARttiType.IsSet,False);
  999. finally
  1000. c.Free;
  1001. end;
  1002. end;
  1003. procedure TTestRTTI.GetTypeInteger;
  1004. var
  1005. LContext: TRttiContext;
  1006. LType: TRttiType;
  1007. begin
  1008. LContext := TRttiContext.Create;
  1009. LType := LContext.GetType(TypeInfo(integer));
  1010. {$ifdef fpc}
  1011. CheckEquals(LType.Name, 'LongInt');
  1012. {$else}
  1013. CheckEquals(LType.Name, 'Integer');
  1014. {$endif}
  1015. LContext.Free;
  1016. end;
  1017. procedure TTestRTTI.GetTypePointer;
  1018. var
  1019. context: TRttiContext;
  1020. t: TRttiType;
  1021. p: TRttiPointerType absolute t;
  1022. begin
  1023. context := TRttiContext.Create;
  1024. try
  1025. t := context.GetType(TypeInfo(Pointer));
  1026. Assert(t is TRttiPointerType, 'Type of Pointer is not a TRttiPointerType');
  1027. Assert(not Assigned(p.ReferredType), 'ReferredType of Pointer is not Nil');
  1028. t := context.GetType(TypeInfo(PLongInt));
  1029. Assert(t is TRttiPointerType, 'Type of Pointer is not a TRttiPointerType');
  1030. Assert(Assigned(p.ReferredType), 'ReferredType of PLongInt is Nil');
  1031. Assert(p.ReferredType = context.GetType(TypeInfo(LongInt)), 'ReferredType of PLongInt is not a LongInt');
  1032. t := context.GetType(TypeInfo(PWideChar));
  1033. Assert(t is TRttiPointerType, 'Type of Pointer is not a TRttiPointerType');
  1034. Assert(Assigned(p.ReferredType), 'ReferredType of PWideChar is Nil');
  1035. Assert(p.ReferredType = context.GetType(TypeInfo(WideChar)), 'ReferredType of PWideChar is not a WideChar');
  1036. finally
  1037. context.Free;
  1038. end;
  1039. end;
  1040. procedure TTestRTTI.GetClassProperties;
  1041. var
  1042. LContext: TRttiContext;
  1043. LType: TRttiType;
  1044. PropList, PropList2: {$ifdef fpc}specialize{$endif} TArray<TRttiProperty>;
  1045. i: LongInt;
  1046. begin
  1047. LContext := TRttiContext.Create;
  1048. LType := LContext.GetType(TypeInfo(TGetClassProperties));
  1049. PropList := LType.GetProperties;
  1050. CheckEquals(4, length(PropList));
  1051. CheckEquals('PubPropRO', PropList[0].Name);
  1052. CheckEquals('PubPropRW', PropList[1].Name);
  1053. CheckEquals('PubPropSetRO', PropList[2].Name);
  1054. CheckEquals('PubPropSetRW', PropList[3].Name);
  1055. LType := LContext.GetType(TypeInfo(TGetClassPropertiesSub));
  1056. PropList2 := LType.GetProperties;
  1057. CheckEquals(Length(PropList), Length(PropList2));
  1058. for i := 0 to High(PropList) do
  1059. Check(PropList[i] = PropList2[i], 'Property instances are not equal');
  1060. LContext.Free;
  1061. end;
  1062. procedure TTestRTTI.GetClassPropertiesValue;
  1063. var
  1064. AGetClassProperties: TGetClassProperties;
  1065. LContext: TRttiContext;
  1066. LType: TRttiType;
  1067. AValue: TValue;
  1068. begin
  1069. LContext := TRttiContext.Create;
  1070. LType := LContext.GetType(TGetClassProperties);
  1071. AGetClassProperties := TGetClassProperties.Create;
  1072. try
  1073. AGetClassProperties.PubPropRW:=12345;
  1074. AValue := LType.GetProperty('PubPropRW').GetValue(AGetClassProperties);
  1075. CheckEquals(12345, AValue.AsInteger);
  1076. finally
  1077. AGetClassProperties.Free;
  1078. end;
  1079. LContext.Free;
  1080. end;
  1081. procedure TTestRTTI.TestInterface;
  1082. var
  1083. context: TRttiContext;
  1084. t: TRttiType;
  1085. ti1, ti2: TRttiInterfaceType;
  1086. methods: {$ifdef fpc}specialize{$endif} TArray<TRttiMethod>;
  1087. params: {$ifdef fpc}specialize{$endif} TArray<TRttiParameter>;
  1088. method: TRttiMethod;
  1089. param: TRttiParameter;
  1090. flag: TParamFlag;
  1091. begin
  1092. context := TRttiContext.Create;
  1093. try
  1094. t := context.GetType(TypeInfo(IInterface));
  1095. Check(t is TRttiInterfaceType, 'Type is not an interface type');
  1096. Check(not Assigned(t.BaseType), 'Base type is assigned');
  1097. ti1 := TRttiInterfaceType(t);
  1098. Check(not Assigned(ti1.BaseType), 'Base type is assigned');
  1099. methods := t.GetMethods;
  1100. CheckEquals(0, Length(methods), 'Overall method count does not match');
  1101. methods := t.GetDeclaredMethods;
  1102. CheckEquals(0, Length(methods), 'Declared method conut does not match');
  1103. t := context.GetType(TypeInfo(ITestInterface));
  1104. Check(t is TRttiInterfaceType, 'Type is not an interface type');
  1105. Check(Assigned(t.BaseType), 'Base type is not assigned');
  1106. Check(t.BaseType = TRttiType(ti1), 'Base type does not match');
  1107. ti2 := TRttiInterfaceType(t);
  1108. Check(Assigned(ti2.BaseType), 'Base type is not assigned');
  1109. Check(ti2.BaseType = ti1, 'Base type does not match');
  1110. methods := t.GetMethods;
  1111. CheckEquals(4, Length(methods), 'Overall method count does not match');
  1112. methods := t.GetDeclaredMethods;
  1113. CheckEquals(4, Length(methods), 'Declared method count does not match');
  1114. method := methods[0];
  1115. CheckEquals(method.Name, 'Test', 'Method name of Test does not match');
  1116. Check(method.CallingConvention = DefaultCC, 'Calling convention of Test does not match');
  1117. Check(method.MethodKind = mkProcedure, 'Method kind of Test does not match');
  1118. Check(method.DispatchKind = dkInterface, 'Dispatch kind of Test does not match');
  1119. Check(not Assigned(method.CodeAddress), 'Code address of Test is not Nil');
  1120. CheckEquals(method.VirtualIndex, 3, 'Virtual index of Test does not match');
  1121. Check(not Assigned(method.ReturnType), 'Return type of Test is not Nil');
  1122. params := method.GetParameters;
  1123. CheckEquals(0, Length(params), 'Parameter count of Test does not match');
  1124. method := methods[1];
  1125. CheckEquals(method.Name, 'Test2', 'Method name of Test2 does not match');
  1126. Check(method.CallingConvention = DefaultCC, 'Calling convention of Test2 does not match');
  1127. Check(method.MethodKind = mkFunction, 'Method kind of Test2 does not match');
  1128. Check(method.DispatchKind = dkInterface, 'Dispatch kind of Test2 does not match');
  1129. Check(not Assigned(method.CodeAddress), 'Code address of Test2 is not Nil');
  1130. CheckEquals(method.VirtualIndex, 4, 'Virtual index of Test2 does not match');
  1131. Check(Assigned(method.ReturnType), 'Return type of Test2 is Nil');
  1132. Check(method.ReturnType.TypeKind = tkInteger, 'Return type of Test2 is not an ordinal');
  1133. params := method.GetParameters;
  1134. CheckEquals(0, Length(params), 'Parameter count of Test2 does not match');
  1135. method := methods[2];
  1136. CheckEquals(method.Name, 'Test3', 'Method name of Test3 does not match');
  1137. Check(method.CallingConvention = DefaultCC, 'Calling convention of Test3 does not match');
  1138. Check(method.MethodKind = mkProcedure, 'Method kind of Test3 does not match');
  1139. Check(method.DispatchKind = dkInterface, 'Dispatch kind of Test3 does not match');
  1140. Check(not Assigned(method.CodeAddress), 'Code address of Test3 is not Nil');
  1141. CheckEquals(method.VirtualIndex, 5, 'Virtual index of Test3 does not match');
  1142. Check(not Assigned(method.ReturnType), 'Return type of Test3 is not Nil');
  1143. params := method.GetParameters;
  1144. CheckEquals(4, Length(params), 'Parameter count of Test3 does not match');
  1145. param := params[0];
  1146. CheckEquals(param.Name, 'aArg1', 'Parameter name of Test3.aArg1 does not match');
  1147. Check(param.Flags = [], 'Parameter flags of Test3.aArg1 do not match');
  1148. Check(Assigned(param.ParamType), 'Parameter type of Test3.aArg1 is Nil');
  1149. Check(param.ParamType.TypeKind = tkInteger, 'Parameter type of Test3.aArg1 is not an ordinal');
  1150. param := params[1];
  1151. CheckEquals(param.Name, 'aArg2', 'Parameter name of Test3.aArg2 does not match');
  1152. Check(param.Flags = [pfConst], 'Parameter flags of Test3.aArg2 do not match');
  1153. Check(Assigned(param.ParamType), 'Parameter type of Test3.aArg2 is Nil');
  1154. Check(param.ParamType.TypeKind = tkAnsiString, 'Parameter type of Test3.aArg2 is not a string');
  1155. param := params[2];
  1156. CheckEquals(param.Name, 'aArg3', 'Parameter name of Test3.aArg3 does not match');
  1157. Check(param.Flags = [pfVar], 'Parameter flags of Test3.aArg3 do not match');
  1158. Check(Assigned(param.ParamType), 'Parameter type of Test3.aArg3 is Nil');
  1159. Check(param.ParamType.TypeKind = {$ifdef fpc}tkBool{$else}tkEnumeration{$endif}, 'Parameter type of Test3.aArg3 is not a boolean');
  1160. param := params[3];
  1161. CheckEquals(param.Name, 'aArg4', 'Parameter name of Test3.aArg4 does not match');
  1162. Check(param.Flags = [pfOut], 'Parameter flags of Test3.aArg4 do not match');
  1163. Check(Assigned(param.ParamType), 'Parameter type of Test3.aArg4 is Nil');
  1164. Check(param.ParamType.TypeKind = tkInteger, 'Parameter type of Test3.aArg4 is not a string');
  1165. method := methods[3];
  1166. CheckEquals(method.Name, 'Test4', 'Method name of Test4 does not match');
  1167. Check(method.CallingConvention = DefaultCC, 'Calling convention of Test4 does not match');
  1168. Check(method.MethodKind = mkFunction, 'Method kind of Test4 does not match');
  1169. Check(method.DispatchKind = dkInterface, 'Dispatch kind of Test4 does not match');
  1170. Check(not Assigned(method.CodeAddress), 'Code address of Test4 is not Nil');
  1171. CheckEquals(method.VirtualIndex, 6, 'Virtual index of Test4 does not match');
  1172. Check(Assigned(method.ReturnType), 'Return type of Test4 is not Nil');
  1173. Check(method.ReturnType.TypeKind = tkAnsiString, 'Return type of Test4 is not a string');
  1174. params := method.GetParameters;
  1175. CheckEquals(2, Length(params), 'Parameter count of Test4 does not match');
  1176. param := params[0];
  1177. CheckEquals(param.Name, 'aArg1', 'Parameter name of Test4.aArg1 does not match');
  1178. Check(param.Flags = [pfArray, pfReference], 'Parameter flags of Test4.aArg1 do not match');
  1179. Check(Assigned(param.ParamType), 'Parameter type of Test4.aArg1 is Nil');
  1180. Check(param.ParamType.TypeKind = tkInteger, 'Parameter type of Test4.aArg1 is not an ordinal');
  1181. param := params[1];
  1182. CheckEquals(param.Name, 'aArg2', 'Parameter name of Test4.aArg2 does not match');
  1183. Check(param.Flags = [pfArray, pfReference], 'Parameter flags of Test4.aArg2 do not match');
  1184. Check(Assigned(param.ParamType), 'Parameter type of Test4.aArg2 is Nil');
  1185. Check(param.ParamType.TypeKind = tkRecord, 'Parameter type of Test4.aArg2 is not a record');
  1186. finally
  1187. context.Free;
  1188. end;
  1189. end;
  1190. procedure TTestRTTI.TestRawThunk;
  1191. var
  1192. intf: IInterface;
  1193. begin
  1194. { we test the raw thunking by instantiating a TVirtualInterface of IInterface }
  1195. { this does not require a function call manager as the thunking is implemented
  1196. directly inside the RTTI unit }
  1197. try
  1198. intf := TVirtualInterface.Create(PTypeInfo(TypeInfo(IInterface))) as IInterface;
  1199. except
  1200. on e: ENotImplemented do
  1201. Ignore('RawThunk not implemented');
  1202. end;
  1203. { if all went well QueryInterface and _AddRef were called and now we call
  1204. _Release as well }
  1205. intf := Nil;
  1206. end;
  1207. {$ifdef fpc}
  1208. procedure TTestRTTI.TestInterfaceRaw;
  1209. var
  1210. context: TRttiContext;
  1211. t: TRttiType;
  1212. ti: TRttiInterfaceType;
  1213. begin
  1214. context := TRttiContext.Create;
  1215. try
  1216. t := context.GetType(TypeInfo(ICORBATest));
  1217. Check(t is TRttiInterfaceType, 'Type is not a raw interface type');
  1218. Check(not Assigned(t.BaseType), 'Base type is assigned');
  1219. ti := TRttiInterfaceType(t);
  1220. Check(not Assigned(ti.BaseType), 'Base type is assigned');
  1221. finally
  1222. context.Free;
  1223. end;
  1224. end;
  1225. {$endif}
  1226. procedure TTestRTTI.TestArray;
  1227. var
  1228. context: TRttiContext;
  1229. t, el: TRttiType;
  1230. a: TRttiArrayType;
  1231. o: TRttiOrdinalType;
  1232. begin
  1233. context := TRttiContext.Create;
  1234. try
  1235. t := context.GetType(PTypeInfo(TypeInfo(TArrayOfLongintStatic)));
  1236. Check(t is TRttiArrayType, 'Type is not a TRttiArrayType');
  1237. a := TRttiArrayType(t);
  1238. CheckEquals(1, a.DimensionCount, 'Dimension count does not match');
  1239. CheckEquals(4, a.TotalElementCount, 'Total element count does not match');
  1240. el := a.ElementType;
  1241. Check(el is TRttiOrdinalType, 'Element type is not a TRttiOrdinalType');
  1242. Check(el = context.GetType(PTypeInfo(TypeInfo(LongInt))), 'Element type is not a LongInt');
  1243. t := a.Dimensions[0];
  1244. {$ifdef fpc}
  1245. Check(t is TRttiOrdinalType, 'Index type is not a TRttiOrdinalType');
  1246. o := TRttiOrdinalType(t);
  1247. { Currently this is a full type :/ }
  1248. {CheckEquals(0, o.MinValue, 'Minimum value of 1st dimension does not match');
  1249. CheckEquals(3, o.MaxValue, 'Maximum value of 1st dimension does not match');}
  1250. {$else}
  1251. Check(t = Nil, 'Index type is not Nil');
  1252. {$endif}
  1253. t := context.GetType(PTypeInfo(TypeInfo(TArrayOfLongint2DStatic)));
  1254. Check(t is TRttiArrayType, 'Type is not a TRttiArrayType');
  1255. a := TRttiArrayType(t);
  1256. CheckEquals(2, a.DimensionCount, 'Dimension count does not match');
  1257. CheckEquals(4 * 3, a.TotalElementCount, 'Total element count does not match');
  1258. el := a.ElementType;
  1259. Check(el is TRttiOrdinalType, 'Element type is not a TRttiOrdinalType');
  1260. Check(el = context.GetType(PTypeInfo(TypeInfo(LongInt))), 'Element type is not a LongInt');
  1261. t := a.Dimensions[0];
  1262. {$ifdef fpc}
  1263. Check(t is TRttiOrdinalType, 'Index type is not a TRttiOrdinalType');
  1264. o := TRttiOrdinalType(t);
  1265. { Currently this is a full type :/ }
  1266. {CheckEquals(0, o.MinValue, 'Minimum value of 1st dimension does not match');
  1267. CheckEquals(3, o.MaxValue, 'Maximum value of 1st dimension does not match');}
  1268. {$else}
  1269. Check(t = Nil, 'Index type is not Nil');
  1270. {$endif}
  1271. t := a.Dimensions[1];
  1272. {$ifdef fpc}
  1273. Check(t is TRttiOrdinalType, 'Index type is not a TRttiOrdinalType');
  1274. o := TRttiOrdinalType(t);
  1275. { Currently this is a full type :/ }
  1276. {CheckEquals(2, o.MinValue, 'Minimum value of 1st dimension does not match');
  1277. CheckEquals(4, o.MaxValue, 'Maximum value of 1st dimension does not match');}
  1278. {$else}
  1279. Check(t = Nil, 'Index type is not Nil');
  1280. {$endif}
  1281. finally
  1282. context.Free;
  1283. end;
  1284. end;
  1285. procedure TTestRTTI.TestDynArray;
  1286. var
  1287. context: TRttiContext;
  1288. t, el: TRttiType;
  1289. a: TRttiDynamicArrayType;
  1290. begin
  1291. context := TRttiContext.Create;
  1292. try
  1293. t := context.GetType(PTypeInfo(TypeInfo(TArrayOfLongintDyn)));
  1294. Check(t is TRttiDynamicArrayType, 'Type is not a TRttiDynamicArrayType');
  1295. a := TRttiDynamicArrayType(t);
  1296. CheckEquals('tests.rtti.types', LowerCase(a.DeclaringUnitName), 'Unit type does not match for dynamic array');
  1297. CheckEquals(a.ElementSize, SizeUInt(SizeOf(LongInt)), 'Element size does not match for dynamic array');
  1298. el := a.ElementType;
  1299. Check(el is TRttiOrdinalType, 'Element type is not a TRttiOrdinalType');
  1300. Check(el = context.GetType(PTypeInfo(TypeInfo(LongInt))), 'Element type is not a LongInt');
  1301. { ToDo: check OLE type }
  1302. finally
  1303. context.Free;
  1304. end;
  1305. end;
  1306. procedure TTestRTTI.TestProcVar;
  1307. var
  1308. context: TRttiContext;
  1309. t: TRttiType;
  1310. p: TRttiProcedureType;
  1311. params: {$ifdef fpc}specialize{$endif} TArray<TRttiParameter>;
  1312. begin
  1313. context := TRttiContext.Create;
  1314. try
  1315. t := context.GetType(PTypeInfo(TypeInfo(TTestProc)));
  1316. Check(Assigned(t), 'Rtti Type is Nil');
  1317. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1318. Check(t is TRttiProcedureType, 'Rtti Type is not a procedure type');
  1319. p := t as TRttiProcedureType;
  1320. Check(p.CallingConvention = DefaultCC, 'Calling convention does not match');
  1321. Check(not Assigned(p.ReturnType), 'Return type is assigned');
  1322. CheckEquals(0, Length(p.GetParameters), 'Procedure variable has parameters');
  1323. t := context.GetType(PTypeInfo(TypeInfo(TTestFunc1)));
  1324. Check(Assigned(t), 'Rtti Type is Nil');
  1325. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1326. Check(t is TRttiProcedureType, 'Rtti Type is not a procedure type');
  1327. p := t as TRttiProcedureType;
  1328. Check(p.CallingConvention = DefaultCC, 'Calling convention does not match');
  1329. Check(Assigned(p.ReturnType), 'Return type is not assigned');
  1330. //Check(p.ReturnType is TRttiOrdinalType, 'Return type is not an ordinal type');
  1331. CheckEquals(0, Length(p.GetParameters), 'Procedure variable has parameters');
  1332. t := context.GetType(PTypeInfo(TypeInfo(TTestFunc2)));
  1333. Check(Assigned(t), 'Rtti Type is Nil');
  1334. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1335. Check(t is TRttiProcedureType, 'Rtti Type is not a procedure type');
  1336. p := t as TRttiProcedureType;
  1337. Check(p.CallingConvention = DefaultCC, 'Calling convention does not match');
  1338. Check(Assigned(p.ReturnType), 'Return type is not assigned');
  1339. Check(p.ReturnType is TRttiStringType, 'Return type is not a string type');
  1340. params := p.GetParameters;
  1341. CheckEquals(2, Length(params), 'Procedure variable has incorrect amount of parameters');
  1342. Check(params[0].ParamType.TypeKind in [tkInteger, tkInt64], 'Parameter 1 is not an ordinal type');
  1343. //Check(params[0].ParamType is TRttiOrdinalType, 'Parameter 1 is not an ordinal type');
  1344. Check(pfArray in params[1].Flags, 'Parameter 2 is not an array');
  1345. Check(params[1].ParamType.TypeKind in [tkInteger, tkInt64], 'Parameter 2 is not an ordinal array');
  1346. finally
  1347. context.Free;
  1348. end;
  1349. end;
  1350. procedure TTestRTTI.TestMethod;
  1351. var
  1352. context: TRttiContext;
  1353. t: TRttiType;
  1354. m: TRttiMethodType;
  1355. params: {$ifdef fpc}specialize{$endif} TArray<TRttiParameter>;
  1356. begin
  1357. context := TRttiContext.Create;
  1358. try
  1359. t := context.GetType(PTypeInfo(TypeInfo(TTestMethod)));
  1360. Check(Assigned(t), 'Rtti Type is Nil');
  1361. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1362. Check(t is TRttiMethodType, 'Rtti Type is not a method type');
  1363. m := t as TRttiMethodType;
  1364. Check(m.CallingConvention = DefaultCC, 'Calling convention does not match');
  1365. Check(not Assigned(m.ReturnType), 'Return type is assigned');
  1366. CheckEquals(0, Length(m.GetParameters), 'Method variable has parameters');
  1367. t := context.GetType(PTypeInfo(TypeInfo(TTestMethod1)));
  1368. Check(Assigned(t), 'Rtti Type is Nil');
  1369. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1370. Check(t is TRttiMethodType, 'Rtti Type is not a method type');
  1371. m := t as TRttiMethodType;
  1372. Check(m.CallingConvention = DefaultCC, 'Calling convention does not match');
  1373. Check(Assigned(m.ReturnType), 'Return type is not assigned');
  1374. //Check(p.ReturnType is TRttiOrdinalType, 'Return type is not an ordinal type');
  1375. CheckEquals(0, Length(m.GetParameters), 'Method variable has parameters');
  1376. t := context.GetType(PTypeInfo(TypeInfo(TTestMethod2)));
  1377. Check(Assigned(t), 'Rtti Type is Nil');
  1378. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1379. Check(t is TRttiMethodType, 'Rtti Type is not a method type');
  1380. m := t as TRttiMethodType;
  1381. Check(m.CallingConvention = DefaultCC, 'Calling convention does not match');
  1382. Check(Assigned(m.ReturnType), 'Return type is not assigned');
  1383. Check(m.ReturnType is TRttiStringType, 'Return type is not a string type');
  1384. params := m.GetParameters;
  1385. CheckEquals(2, Length(params), 'Method variable has incorrect amount of parameters');
  1386. Check(params[0].ParamType.TypeKind in [tkInteger, tkInt64], 'Parameter 1 is not an ordinal type');
  1387. //Check(params[0].ParamType is TRttiOrdinalType, 'Parameter 1 is not an ordinal type');
  1388. Check(pfArray in params[1].Flags, 'Parameter 2 is not an array');
  1389. Check(params[1].ParamType.TypeKind in [tkInteger, tkInt64], 'Parameter 2 is not an ordinal array');
  1390. finally
  1391. context.Free;
  1392. end;
  1393. end;
  1394. initialization
  1395. {$ifdef fpc}
  1396. RegisterTest(TTestRTTI);
  1397. {$else fpc}
  1398. RegisterTest(TTestRTTI.Suite);
  1399. {$endif fpc}
  1400. end.