tests.rtti.pas 63 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969
  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. <<<<<<< HEAD
  1082. procedure TTestRTTI.TestInterface;
  1083. =======
  1084. test.value1 := 42;
  1085. test.value2 := 'Hello World';
  1086. TValue.Make(@test, TypeInfo(TTestRecord), value);
  1087. Check(value.GetReferenceToRawData <> @test, 'Reference to record is equal');
  1088. Check(PTestRecord(value.GetReferenceToRawData)^.value1 = PTestRecord(@test)^.value1, 'Reference to record data value1 differs');
  1089. Check(PTestRecord(value.GetReferenceToRawData)^.value2 = PTestRecord(@test)^.value2, 'Reference to record data value2 differs');
  1090. SetLength(arrdyn, 3);
  1091. arrdyn[0] := 42;
  1092. arrdyn[1] := 23;
  1093. arrdyn[2] := 49;
  1094. TValue.Make(@arrdyn, TypeInfo(TArrayOfLongintDyn), value);
  1095. Check(PPointer(value.GetReferenceToRawData)^ = Pointer(arrdyn), 'Reference to dynamic array data differs');
  1096. arrstat[0] := 42;
  1097. arrstat[1] := 23;
  1098. arrstat[2] := 49;
  1099. arrstat[3] := 59;
  1100. TValue.Make(@arrstat, TypeInfo(TArrayOfLongintStatic), value);
  1101. Check(value.GetReferenceToRawData <> @arrstat, 'Reference to static array is equal');
  1102. Check(PLongInt(value.GetReferenceToRawData)^ = PLongInt(@arrstat)^, 'Reference to static array data differs');
  1103. end;
  1104. procedure TTestCase1.TestReferenceRawDataEmpty;
  1105. var
  1106. value: TValue;
  1107. begin
  1108. TValue.Make(Nil, TypeInfo(String), value);
  1109. Check(Assigned(value.GetReferenceToRawData()), 'Reference to empty String is not assigned');
  1110. Check(not Assigned(PPointer(value.GetReferenceToRawData)^), 'Empty String data is assigned');
  1111. TValue.Make(Nil, TypeInfo(IInterface), value);
  1112. Check(Assigned(value.GetReferenceToRawData()), 'Reference to empty interface is not assigned');
  1113. Check(not Assigned(PPointer(value.GetReferenceToRawData)^), 'Empty interface data is assigned');
  1114. TValue.Make(Nil, TypeInfo(LongInt), value);
  1115. Check(Assigned(value.GetReferenceToRawData()), 'Reference to empty LongInt is not assigned');
  1116. Check(PLongInt(value.GetReferenceToRawData)^ = 0, 'Empty longint data is not 0');
  1117. TValue.Make(Nil, TypeInfo(TTestRecord), value);
  1118. Check(Assigned(value.GetReferenceToRawData()), 'Reference to empty record is not assigned');
  1119. Check(PTestRecord(value.GetReferenceToRawData)^.value1 = 0, 'Empty record data value1 is not 0');
  1120. Check(PTestRecord(value.GetReferenceToRawData)^.value2 = '', 'Empty record data value2 is not empty');
  1121. TValue.Make(Nil, TypeInfo(TArrayOfLongintDyn), value);
  1122. Check(Assigned(value.GetReferenceToRawData()), 'Reference to empty dynamic array is not assigned');
  1123. Check(not Assigned(PPointer(value.GetReferenceToRawData)^), 'Empty dynamic array data is assigned');
  1124. TValue.Make(Nil, TypeInfo(TArrayOfLongintStatic), value);
  1125. Check(Assigned(value.GetReferenceToRawData()), 'Reference to empty static array is not assigned');
  1126. Check(PLongInt(value.GetReferenceToRawData)^ = 0, 'Empty static array data is not 0');
  1127. end;
  1128. procedure TTestCase1.TestDataSize;
  1129. var
  1130. u8: UInt8;
  1131. u16: UInt16;
  1132. u32: UInt32;
  1133. u64: UInt64;
  1134. s8: Int8;
  1135. s16: Int16;
  1136. s32: Int32;
  1137. s64: Int64;
  1138. f32: Single;
  1139. f64: Double;
  1140. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1141. f80: Extended;
  1142. {$endif}
  1143. fco: Comp;
  1144. fcu: Currency;
  1145. ss: ShortString;
  1146. sa: AnsiString;
  1147. su: UnicodeString;
  1148. sw: WideString;
  1149. o: TObject;
  1150. c: TClass;
  1151. i: IInterface;
  1152. ad: TArrayOfLongintDyn;
  1153. _as: TArrayOfLongintStatic;
  1154. b8: Boolean;
  1155. {$ifdef fpc}
  1156. b16: Boolean16;
  1157. b32: Boolean32;
  1158. b64: Boolean64;
  1159. {$endif}
  1160. bl8: ByteBool;
  1161. bl16: WordBool;
  1162. bl32: LongBool;
  1163. {$ifdef fpc}
  1164. bl64: QWordBool;
  1165. {$endif}
  1166. e: TTestEnum;
  1167. s: TTestSet;
  1168. t: TTestRecord;
  1169. p: Pointer;
  1170. proc: TTestProc;
  1171. method: TTestMethod;
  1172. value: TValue;
  1173. begin
  1174. u8:=245;
  1175. TValue.Make(@u8, TypeInfo(UInt8), value);
  1176. CheckEquals(1, value.DataSize, 'Size of UInt8 differs');
  1177. u16:=789;
  1178. TValue.Make(@u16, TypeInfo(UInt16), value);
  1179. CheckEquals(2, value.DataSize, 'Size of UInt16 differs');
  1180. u32:=568789;
  1181. TValue.Make(@u32, TypeInfo(UInt32), value);
  1182. CheckEquals(4, value.DataSize, 'Size of UInt32 differs');
  1183. u64:=$abdcefadbcef;
  1184. TValue.Make(@u64, TypeInfo(UInt64), value);
  1185. CheckEquals(8, value.DataSize, 'Size of UInt64 differs');
  1186. s8:=-32;
  1187. TValue.Make(@s8, TypeInfo(Int8), value);
  1188. CheckEquals(1, value.DataSize, 'Size of Int8 differs');
  1189. s16:=-5345;
  1190. TValue.Make(@s16, TypeInfo(Int16), value);
  1191. CheckEquals(2, value.DataSize, 'Size of Int16 differs');
  1192. s32:=-234567;
  1193. TValue.Make(@s32, TypeInfo(Int32), value);
  1194. CheckEquals(4, value.DataSize, 'Size of Int32 differs');
  1195. s64:=23456789012;
  1196. TValue.Make(@s64, TypeInfo(Int64), value);
  1197. CheckEquals(8, value.DataSize, 'Size of Int64 differs');
  1198. b8:=false;
  1199. TValue.Make(@b8, TypeInfo(Boolean), value);
  1200. CheckEquals(1, value.DataSize, 'Size of Boolean differs');
  1201. {$ifdef fpc}
  1202. b16:=true;
  1203. TValue.Make(@b16, TypeInfo(Boolean16), value);
  1204. CheckEquals(2, value.DataSize, 'Size of Boolean16 differs');
  1205. b32:=false;
  1206. TValue.Make(@b32, TypeInfo(Boolean32), value);
  1207. CheckEquals(4, value.DataSize, 'Size of Boolean32 differs');
  1208. b64:=true;
  1209. TValue.Make(@b64, TypeInfo(Boolean64), value);
  1210. CheckEquals(8, value.DataSize, 'Size of Boolean64 differs');
  1211. {$endif}
  1212. bl8:=true;
  1213. TValue.Make(@bl8, TypeInfo(ByteBool), value);
  1214. CheckEquals(1, value.DataSize, 'Size of ByteBool differs');
  1215. bl16:=false;
  1216. TValue.Make(@bl16, TypeInfo(WordBool), value);
  1217. CheckEquals(2, value.DataSize, 'Size of WordBool differs');
  1218. bl32:=false;
  1219. TValue.Make(@bl32, TypeInfo(LongBool), value);
  1220. CheckEquals(4, value.DataSize, 'Size of LongBool differs');
  1221. {$ifdef fpc}
  1222. bl64:=true;
  1223. TValue.Make(@bl64, TypeInfo(QWordBool), value);
  1224. CheckEquals(8, value.DataSize, 'Size of QWordBool differs');
  1225. {$endif}
  1226. f32:=4.567;
  1227. TValue.Make(@f32, TypeInfo(Single), value);
  1228. CheckEquals(4, value.DataSize, 'Size of Single differs');
  1229. f64:=-3456.678;
  1230. TValue.Make(@f64, TypeInfo(Double), value);
  1231. CheckEquals(8, value.DataSize, 'Size of Double differs');
  1232. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1233. f80:=-2345.678;
  1234. TValue.Make(@f80, TypeInfo(Extended), value);
  1235. CheckEquals(10, value.DataSize, 'Size of Extended differs');
  1236. {$endif}
  1237. fcu:=56.78;
  1238. TValue.Make(@fcu, TypeInfo(Currency), value);
  1239. CheckEquals(SizeOf(Currency), value.DataSize, 'Size of Currency differs');
  1240. fco:=456;
  1241. TValue.Make(@fco, TypeInfo(Comp), value);
  1242. CheckEquals(SizeOf(Comp), value.DataSize, 'Size of Comp differs');
  1243. ss := '';
  1244. TValue.Make(@ss, TypeInfo(ShortString), value);
  1245. CheckEquals(254, value.DataSize, 'Size ofShortString differs');
  1246. sa:= '';
  1247. TValue.Make(@sa, TypeInfo(AnsiString), value);
  1248. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of AnsiString differs');
  1249. sw := '';
  1250. TValue.Make(@sw, TypeInfo(WideString), value);
  1251. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of WideString differs');
  1252. su:='';
  1253. TValue.Make(@su, TypeInfo(UnicodeString), value);
  1254. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of UnicodeString differs');
  1255. o := TTestValueClass.Create;
  1256. TValue.Make(@o, TypeInfo(TObject), value);
  1257. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of TObject differs');
  1258. o.Free;
  1259. c := TObject;
  1260. TValue.Make(@c, TypeInfo(TClass), value);
  1261. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of TClass differs');
  1262. i := Nil;
  1263. TValue.Make(@i, TypeInfo(IInterface), value);
  1264. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of IInterface differs');
  1265. TValue.Make(@t, TypeInfo(TTestRecord), value);
  1266. CheckEquals(SizeOf(TTestRecord), value.DataSize, 'Size of TTestRecord differs');
  1267. proc := Nil;
  1268. TValue.Make(@proc, TypeInfo(TTestProc), value);
  1269. CheckEquals(SizeOf(TTestProc), value.DataSize, 'Size of TTestProc differs');
  1270. method := Nil;
  1271. TValue.Make(@method, TypeInfo(TTestMethod), value);
  1272. CheckEquals(SizeOf(TTestMethod), value.DataSize, 'Size of TTestMethod differs');
  1273. TValue.Make(@_as, TypeInfo(TArrayOfLongintStatic), value);
  1274. CheckEquals(SizeOf(TArrayOfLongintStatic), value.DataSize, 'Size of TArrayOfLongintStatic differs');
  1275. TValue.Make(@ad, TypeInfo(TArrayOfLongintDyn), value);
  1276. CheckEquals(SizeOf(TArrayOfLongintDyn), value.DataSize, 'Size of TArrayOfLongintDyn differs');
  1277. e:=low(TTestEnum);
  1278. TValue.Make(@e, TypeInfo(TTestEnum), value);
  1279. CheckEquals(SizeOf(TTestEnum), value.DataSize, 'Size of TTestEnum differs');
  1280. s:=[low(TTestEnum),high(TTestEnum)];
  1281. TValue.Make(@s, TypeInfo(TTestSet), value);
  1282. CheckEquals(SizeOf(TTestSet), value.DataSize, 'Size of TTestSet differs');
  1283. p := Nil;
  1284. TValue.Make(@p, TypeInfo(Pointer), value);
  1285. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of Pointer differs');
  1286. end;
  1287. procedure TTestCase1.TestDataSizeEmpty;
  1288. var
  1289. value: TValue;
  1290. begin
  1291. TValue.Make(Nil, TypeInfo(UInt8), value);
  1292. CheckEquals(1, value.DataSize, 'Size of UInt8 differs');
  1293. TValue.Make(Nil, TypeInfo(UInt16), value);
  1294. CheckEquals(2, value.DataSize, 'Size of UInt16 differs');
  1295. TValue.Make(Nil, TypeInfo(UInt32), value);
  1296. CheckEquals(4, value.DataSize, 'Size of UInt32 differs');
  1297. TValue.Make(Nil, TypeInfo(UInt64), value);
  1298. CheckEquals(8, value.DataSize, 'Size of UInt64 differs');
  1299. TValue.Make(Nil, TypeInfo(Int8), value);
  1300. CheckEquals(1, value.DataSize, 'Size of Int8 differs');
  1301. TValue.Make(Nil, TypeInfo(Int16), value);
  1302. CheckEquals(2, value.DataSize, 'Size of Int16 differs');
  1303. TValue.Make(Nil, TypeInfo(Int32), value);
  1304. CheckEquals(4, value.DataSize, 'Size of Int32 differs');
  1305. TValue.Make(Nil, TypeInfo(Int64), value);
  1306. CheckEquals(8, value.DataSize, 'Size of Int64 differs');
  1307. TValue.Make(Nil, TypeInfo(Boolean), value);
  1308. CheckEquals(1, value.DataSize, 'Size of Boolean differs');
  1309. {$ifdef fpc}
  1310. TValue.Make(Nil, TypeInfo(Boolean16), value);
  1311. CheckEquals(2, value.DataSize, 'Size of Boolean16 differs');
  1312. TValue.Make(Nil, TypeInfo(Boolean32), value);
  1313. CheckEquals(4, value.DataSize, 'Size of Boolean32 differs');
  1314. TValue.Make(Nil, TypeInfo(Boolean64), value);
  1315. CheckEquals(8, value.DataSize, 'Size of Boolean64 differs');
  1316. {$endif}
  1317. TValue.Make(Nil, TypeInfo(ByteBool), value);
  1318. CheckEquals(1, value.DataSize, 'Size of ByteBool differs');
  1319. TValue.Make(Nil, TypeInfo(WordBool), value);
  1320. CheckEquals(2, value.DataSize, 'Size of WordBool differs');
  1321. TValue.Make(Nil, TypeInfo(LongBool), value);
  1322. CheckEquals(4, value.DataSize, 'Size of LongBool differs');
  1323. {$ifdef fpc}
  1324. TValue.Make(Nil, TypeInfo(QWordBool), value);
  1325. CheckEquals(8, value.DataSize, 'Size of QWordBool differs');
  1326. {$endif}
  1327. TValue.Make(Nil, TypeInfo(Single), value);
  1328. CheckEquals(4, value.DataSize, 'Size of Single differs');
  1329. TValue.Make(Nil, TypeInfo(Double), value);
  1330. CheckEquals(8, value.DataSize, 'Size of Double differs');
  1331. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1332. TValue.Make(Nil, TypeInfo(Extended), value);
  1333. CheckEquals(10, value.DataSize, 'Size of Extended differs');
  1334. {$endif}
  1335. TValue.Make(Nil, TypeInfo(Currency), value);
  1336. CheckEquals(SizeOf(Currency), value.DataSize, 'Size of Currency differs');
  1337. TValue.Make(Nil, TypeInfo(Comp), value);
  1338. CheckEquals(SizeOf(Comp), value.DataSize, 'Size of Comp differs');
  1339. TValue.Make(Nil, TypeInfo(ShortString), value);
  1340. CheckEquals(254, value.DataSize, 'Size of ShortString differs');
  1341. TValue.Make(Nil, TypeInfo(AnsiString), value);
  1342. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of Pointer differs');
  1343. TValue.Make(Nil, TypeInfo(WideString), value);
  1344. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of WideString differs');
  1345. TValue.Make(Nil, TypeInfo(UnicodeString), value);
  1346. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of UnicodeString differs');
  1347. TValue.Make(Nil, TypeInfo(TObject), value);
  1348. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of TObject differs');
  1349. TValue.Make(Nil, TypeInfo(TClass), value);
  1350. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of TClass differs');
  1351. TValue.Make(Nil, TypeInfo(IInterface), value);
  1352. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of IInterface differs');
  1353. TValue.Make(Nil, TypeInfo(TTestRecord), value);
  1354. CheckEquals(SizeOf(TTestRecord), value.DataSize, 'Size of TTestRecord differs');
  1355. TValue.Make(Nil, TypeInfo(TTestProc), value);
  1356. CheckEquals(SizeOf(TTestProc), value.DataSize, 'Size of TTestProc differs');
  1357. TValue.Make(Nil, TypeInfo(TTestMethod), value);
  1358. CheckEquals(SizeOf(TTestMethod), value.DataSize, 'Size of TTestMethod differs');
  1359. TValue.Make(Nil, TypeInfo(TArrayOfLongintStatic), value);
  1360. CheckEquals(SizeOf(TArrayOfLongintStatic), value.DataSize, 'Size of TArrayOfLongintStatic differs');
  1361. TValue.Make(Nil, TypeInfo(TArrayOfLongintDyn), value);
  1362. CheckEquals(SizeOf(TArrayOfLongintDyn), value.DataSize, 'Size of TArrayOfLongintDyn differs');
  1363. TValue.Make(Nil, TypeInfo(TTestEnum), value);
  1364. CheckEquals(SizeOf(TTestEnum), value.DataSize, 'Size of TTestEnum differs');
  1365. TValue.Make(Nil, TypeInfo(TTestSet), value);
  1366. CheckEquals(SizeOf(TTestSet), value.DataSize, 'Size of TTestSet differs');
  1367. TValue.Make(Nil, TypeInfo(Pointer), value);
  1368. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of Pointer differs');
  1369. end;
  1370. procedure TTestCase1.TestIsManaged;
  1371. begin
  1372. CheckEquals(true, IsManaged(TypeInfo(ansistring)), 'IsManaged for tkAString');
  1373. CheckEquals(true, IsManaged(TypeInfo(widestring)), 'IsManaged for tkWString');
  1374. CheckEquals(true, IsManaged(TypeInfo(Variant)), 'IsManaged for tkVariant');
  1375. CheckEquals(true, IsManaged(TypeInfo(TArrayOfManagedRec)),
  1376. 'IsManaged for tkArray (with managed ElType)');
  1377. CheckEquals(true, IsManaged(TypeInfo(TArrayOfString)),
  1378. 'IsManaged for tkArray (with managed ElType)');
  1379. CheckEquals(true, IsManaged(TypeInfo(TManagedRec)), 'IsManaged for tkRecord');
  1380. {$ifdef fpc}
  1381. CheckEquals(true, IsManaged(TypeInfo(TManagedRecOp)), 'IsManaged for tkRecord');
  1382. {$endif}
  1383. CheckEquals(true, IsManaged(TypeInfo(IInterface)), 'IsManaged for tkInterface');
  1384. CheckEquals(true, IsManaged(TypeInfo(TManagedObj)), 'IsManaged for tkObject');
  1385. {$ifdef fpc}
  1386. CheckEquals(true, IsManaged(TypeInfo(specialize TArray<byte>)), 'IsManaged for tkDynArray');
  1387. {$else}
  1388. CheckEquals(true, IsManaged(TypeInfo(TArray<byte>)), 'IsManaged for tkDynArray');
  1389. {$endif}
  1390. CheckEquals(true, IsManaged(TypeInfo(unicodestring)), 'IsManaged for tkUString');
  1391. CheckEquals(false, IsManaged(TypeInfo(shortstring)), 'IsManaged for tkSString');
  1392. CheckEquals(false, IsManaged(TypeInfo(Byte)), 'IsManaged for tkInteger');
  1393. CheckEquals(false, IsManaged(TypeInfo(AnsiChar)), 'IsManaged for tkChar');
  1394. CheckEquals(false, IsManaged(TypeInfo(TTestEnum)), 'IsManaged for tkEnumeration');
  1395. CheckEquals(false, IsManaged(TypeInfo(Single)), 'IsManaged for tkFloat');
  1396. CheckEquals(false, IsManaged(TypeInfo(TTestSet)), 'IsManaged for tkSet');
  1397. {$ifdef fpc}
  1398. CheckEquals(false, IsManaged(TypeInfo(TTestMethod)), 'IsManaged for tkMethod');
  1399. {$else}
  1400. { Delphi bug (or sabotage). For some reason Delphi considers method pointers to be managed (only in newer versions, probably since XE7) :/ }
  1401. CheckEquals({$if RTLVersion>=28}true{$else}false{$endif}, IsManaged(TypeInfo(TTestMethod)), 'IsManaged for tkMethod');
  1402. {$endif}
  1403. CheckEquals(false, IsManaged(TypeInfo(TArrayOfByte)),
  1404. 'IsManaged for tkArray (with non managed ElType)');
  1405. CheckEquals(false, IsManaged(TypeInfo(TArrayOfNonManagedRec)),
  1406. 'IsManaged for tkArray (with non managed ElType)');
  1407. CheckEquals(false, IsManaged(TypeInfo(TNonManagedRec)), 'IsManaged for tkRecord');
  1408. CheckEquals(false, IsManaged(TypeInfo(TObject)), 'IsManaged for tkClass');
  1409. CheckEquals(false, IsManaged(TypeInfo(TNonManagedObj)), 'IsManaged for tkObject');
  1410. CheckEquals(false, IsManaged(TypeInfo(WideChar)), 'IsManaged for tkWChar');
  1411. CheckEquals(false, IsManaged(TypeInfo(Boolean)), 'IsManaged for tkBool');
  1412. CheckEquals(false, IsManaged(TypeInfo(Int64)), 'IsManaged for tkInt64');
  1413. CheckEquals(false, IsManaged(TypeInfo(UInt64)), 'IsManaged for tkQWord');
  1414. {$ifdef fpc}
  1415. CheckEquals(false, IsManaged(TypeInfo(ICORBATest)), 'IsManaged for tkInterfaceRaw');
  1416. {$endif}
  1417. CheckEquals(false, IsManaged(TypeInfo(TTestProc)), 'IsManaged for tkProcVar');
  1418. CheckEquals(false, IsManaged(TypeInfo(TTestHelper)), 'IsManaged for tkHelper');
  1419. {$ifdef fpc}
  1420. CheckEquals(false, IsManaged(TypeInfo(file)), 'IsManaged for tkFile');
  1421. {$endif}
  1422. CheckEquals(false, IsManaged(TypeInfo(TClass)), 'IsManaged for tkClassRef');
  1423. CheckEquals(false, IsManaged(TypeInfo(Pointer)), 'IsManaged for tkPointer');
  1424. CheckEquals(false, IsManaged(nil), 'IsManaged for nil');
  1425. end;
  1426. {$ifdef fpc}
  1427. procedure TTestCase1.TestOpenArrayToDyn;
  1428. procedure OpenArrayProc(aArr: array of LongInt);
  1429. var
  1430. value: TValue;
  1431. begin
  1432. {$ifndef InLazIDE}
  1433. value := specialize OpenArrayToDynArrayValue<LongInt>(aArr);
  1434. {$endif}
  1435. CheckEquals(value.IsArray, True);
  1436. CheckEquals(value.IsOpenArray, False);
  1437. CheckEquals(value.IsObject, False);
  1438. CheckEquals(value.IsOrdinal, False);
  1439. CheckEquals(value.IsClass, False);
  1440. CheckEquals(value.GetArrayLength, 2);
  1441. CheckEquals(value.GetArrayElement(0).AsInteger, 42);
  1442. CheckEquals(value.GetArrayElement(1).AsInteger, 84);
  1443. value.SetArrayElement(0, 21);
  1444. { since this is a copy the original array is not modified! }
  1445. CheckEquals(aArr[0], 42);
  1446. end;
  1447. begin
  1448. OpenArrayProc([42, 84]);
  1449. end;
  1450. {$endif}
  1451. procedure TTestCase1.TestInterface;
  1452. >>>>>>> a86fa16f98 (* PChar -> PAnsiChar)
  1453. var
  1454. context: TRttiContext;
  1455. t: TRttiType;
  1456. ti1, ti2: TRttiInterfaceType;
  1457. methods: {$ifdef fpc}specialize{$endif} TArray<TRttiMethod>;
  1458. params: {$ifdef fpc}specialize{$endif} TArray<TRttiParameter>;
  1459. method: TRttiMethod;
  1460. param: TRttiParameter;
  1461. flag: TParamFlag;
  1462. begin
  1463. context := TRttiContext.Create;
  1464. try
  1465. t := context.GetType(TypeInfo(IInterface));
  1466. Check(t is TRttiInterfaceType, 'Type is not an interface type');
  1467. Check(not Assigned(t.BaseType), 'Base type is assigned');
  1468. ti1 := TRttiInterfaceType(t);
  1469. Check(not Assigned(ti1.BaseType), 'Base type is assigned');
  1470. methods := t.GetMethods;
  1471. CheckEquals(0, Length(methods), 'Overall method count does not match');
  1472. methods := t.GetDeclaredMethods;
  1473. CheckEquals(0, Length(methods), 'Declared method conut does not match');
  1474. t := context.GetType(TypeInfo(ITestInterface));
  1475. Check(t is TRttiInterfaceType, 'Type is not an interface type');
  1476. Check(Assigned(t.BaseType), 'Base type is not assigned');
  1477. Check(t.BaseType = TRttiType(ti1), 'Base type does not match');
  1478. ti2 := TRttiInterfaceType(t);
  1479. Check(Assigned(ti2.BaseType), 'Base type is not assigned');
  1480. Check(ti2.BaseType = ti1, 'Base type does not match');
  1481. methods := t.GetMethods;
  1482. CheckEquals(4, Length(methods), 'Overall method count does not match');
  1483. methods := t.GetDeclaredMethods;
  1484. CheckEquals(4, Length(methods), 'Declared method count does not match');
  1485. method := methods[0];
  1486. CheckEquals(method.Name, 'Test', 'Method name of Test does not match');
  1487. Check(method.CallingConvention = DefaultCC, 'Calling convention of Test does not match');
  1488. Check(method.MethodKind = mkProcedure, 'Method kind of Test does not match');
  1489. Check(method.DispatchKind = dkInterface, 'Dispatch kind of Test does not match');
  1490. Check(not Assigned(method.CodeAddress), 'Code address of Test is not Nil');
  1491. CheckEquals(method.VirtualIndex, 3, 'Virtual index of Test does not match');
  1492. Check(not Assigned(method.ReturnType), 'Return type of Test is not Nil');
  1493. params := method.GetParameters;
  1494. CheckEquals(0, Length(params), 'Parameter count of Test does not match');
  1495. method := methods[1];
  1496. CheckEquals(method.Name, 'Test2', 'Method name of Test2 does not match');
  1497. Check(method.CallingConvention = DefaultCC, 'Calling convention of Test2 does not match');
  1498. Check(method.MethodKind = mkFunction, 'Method kind of Test2 does not match');
  1499. Check(method.DispatchKind = dkInterface, 'Dispatch kind of Test2 does not match');
  1500. Check(not Assigned(method.CodeAddress), 'Code address of Test2 is not Nil');
  1501. CheckEquals(method.VirtualIndex, 4, 'Virtual index of Test2 does not match');
  1502. Check(Assigned(method.ReturnType), 'Return type of Test2 is Nil');
  1503. Check(method.ReturnType.TypeKind = tkInteger, 'Return type of Test2 is not an ordinal');
  1504. params := method.GetParameters;
  1505. CheckEquals(0, Length(params), 'Parameter count of Test2 does not match');
  1506. method := methods[2];
  1507. CheckEquals(method.Name, 'Test3', 'Method name of Test3 does not match');
  1508. Check(method.CallingConvention = DefaultCC, 'Calling convention of Test3 does not match');
  1509. Check(method.MethodKind = mkProcedure, 'Method kind of Test3 does not match');
  1510. Check(method.DispatchKind = dkInterface, 'Dispatch kind of Test3 does not match');
  1511. Check(not Assigned(method.CodeAddress), 'Code address of Test3 is not Nil');
  1512. CheckEquals(method.VirtualIndex, 5, 'Virtual index of Test3 does not match');
  1513. Check(not Assigned(method.ReturnType), 'Return type of Test3 is not Nil');
  1514. params := method.GetParameters;
  1515. CheckEquals(4, Length(params), 'Parameter count of Test3 does not match');
  1516. param := params[0];
  1517. CheckEquals(param.Name, 'aArg1', 'Parameter name of Test3.aArg1 does not match');
  1518. Check(param.Flags = [], 'Parameter flags of Test3.aArg1 do not match');
  1519. Check(Assigned(param.ParamType), 'Parameter type of Test3.aArg1 is Nil');
  1520. Check(param.ParamType.TypeKind = tkInteger, 'Parameter type of Test3.aArg1 is not an ordinal');
  1521. param := params[1];
  1522. CheckEquals(param.Name, 'aArg2', 'Parameter name of Test3.aArg2 does not match');
  1523. Check(param.Flags = [pfConst], 'Parameter flags of Test3.aArg2 do not match');
  1524. Check(Assigned(param.ParamType), 'Parameter type of Test3.aArg2 is Nil');
  1525. Check(param.ParamType.TypeKind = tkAnsiString, 'Parameter type of Test3.aArg2 is not a string');
  1526. param := params[2];
  1527. CheckEquals(param.Name, 'aArg3', 'Parameter name of Test3.aArg3 does not match');
  1528. Check(param.Flags = [pfVar], 'Parameter flags of Test3.aArg3 do not match');
  1529. Check(Assigned(param.ParamType), 'Parameter type of Test3.aArg3 is Nil');
  1530. Check(param.ParamType.TypeKind = {$ifdef fpc}tkBool{$else}tkEnumeration{$endif}, 'Parameter type of Test3.aArg3 is not a boolean');
  1531. param := params[3];
  1532. CheckEquals(param.Name, 'aArg4', 'Parameter name of Test3.aArg4 does not match');
  1533. Check(param.Flags = [pfOut], 'Parameter flags of Test3.aArg4 do not match');
  1534. Check(Assigned(param.ParamType), 'Parameter type of Test3.aArg4 is Nil');
  1535. Check(param.ParamType.TypeKind = tkInteger, 'Parameter type of Test3.aArg4 is not a string');
  1536. method := methods[3];
  1537. CheckEquals(method.Name, 'Test4', 'Method name of Test4 does not match');
  1538. Check(method.CallingConvention = DefaultCC, 'Calling convention of Test4 does not match');
  1539. Check(method.MethodKind = mkFunction, 'Method kind of Test4 does not match');
  1540. Check(method.DispatchKind = dkInterface, 'Dispatch kind of Test4 does not match');
  1541. Check(not Assigned(method.CodeAddress), 'Code address of Test4 is not Nil');
  1542. CheckEquals(method.VirtualIndex, 6, 'Virtual index of Test4 does not match');
  1543. Check(Assigned(method.ReturnType), 'Return type of Test4 is not Nil');
  1544. Check(method.ReturnType.TypeKind = tkAnsiString, 'Return type of Test4 is not a string');
  1545. params := method.GetParameters;
  1546. CheckEquals(2, Length(params), 'Parameter count of Test4 does not match');
  1547. param := params[0];
  1548. CheckEquals(param.Name, 'aArg1', 'Parameter name of Test4.aArg1 does not match');
  1549. Check(param.Flags = [pfArray, pfReference], 'Parameter flags of Test4.aArg1 do not match');
  1550. Check(Assigned(param.ParamType), 'Parameter type of Test4.aArg1 is Nil');
  1551. Check(param.ParamType.TypeKind = tkInteger, 'Parameter type of Test4.aArg1 is not an ordinal');
  1552. param := params[1];
  1553. CheckEquals(param.Name, 'aArg2', 'Parameter name of Test4.aArg2 does not match');
  1554. Check(param.Flags = [pfArray, pfReference], 'Parameter flags of Test4.aArg2 do not match');
  1555. Check(Assigned(param.ParamType), 'Parameter type of Test4.aArg2 is Nil');
  1556. Check(param.ParamType.TypeKind = tkRecord, 'Parameter type of Test4.aArg2 is not a record');
  1557. finally
  1558. context.Free;
  1559. end;
  1560. end;
  1561. procedure TTestRTTI.TestRawThunk;
  1562. var
  1563. intf: IInterface;
  1564. begin
  1565. { we test the raw thunking by instantiating a TVirtualInterface of IInterface }
  1566. { this does not require a function call manager as the thunking is implemented
  1567. directly inside the RTTI unit }
  1568. try
  1569. intf := TVirtualInterface.Create(PTypeInfo(TypeInfo(IInterface))) as IInterface;
  1570. except
  1571. on e: ENotImplemented do
  1572. Ignore('RawThunk not implemented');
  1573. end;
  1574. { if all went well QueryInterface and _AddRef were called and now we call
  1575. _Release as well }
  1576. intf := Nil;
  1577. end;
  1578. {$ifdef fpc}
  1579. procedure TTestRTTI.TestInterfaceRaw;
  1580. var
  1581. context: TRttiContext;
  1582. t: TRttiType;
  1583. ti: TRttiInterfaceType;
  1584. begin
  1585. context := TRttiContext.Create;
  1586. try
  1587. t := context.GetType(TypeInfo(ICORBATest));
  1588. Check(t is TRttiInterfaceType, 'Type is not a raw interface type');
  1589. Check(not Assigned(t.BaseType), 'Base type is assigned');
  1590. ti := TRttiInterfaceType(t);
  1591. Check(not Assigned(ti.BaseType), 'Base type is assigned');
  1592. finally
  1593. context.Free;
  1594. end;
  1595. end;
  1596. {$endif}
  1597. procedure TTestRTTI.TestArray;
  1598. var
  1599. context: TRttiContext;
  1600. t, el: TRttiType;
  1601. a: TRttiArrayType;
  1602. o: TRttiOrdinalType;
  1603. begin
  1604. context := TRttiContext.Create;
  1605. try
  1606. t := context.GetType(PTypeInfo(TypeInfo(TArrayOfLongintStatic)));
  1607. Check(t is TRttiArrayType, 'Type is not a TRttiArrayType');
  1608. a := TRttiArrayType(t);
  1609. CheckEquals(1, a.DimensionCount, 'Dimension count does not match');
  1610. CheckEquals(4, a.TotalElementCount, 'Total element count does not match');
  1611. el := a.ElementType;
  1612. Check(el is TRttiOrdinalType, 'Element type is not a TRttiOrdinalType');
  1613. Check(el = context.GetType(PTypeInfo(TypeInfo(LongInt))), 'Element type is not a LongInt');
  1614. t := a.Dimensions[0];
  1615. {$ifdef fpc}
  1616. Check(t is TRttiOrdinalType, 'Index type is not a TRttiOrdinalType');
  1617. o := TRttiOrdinalType(t);
  1618. { Currently this is a full type :/ }
  1619. {CheckEquals(0, o.MinValue, 'Minimum value of 1st dimension does not match');
  1620. CheckEquals(3, o.MaxValue, 'Maximum value of 1st dimension does not match');}
  1621. {$else}
  1622. Check(t = Nil, 'Index type is not Nil');
  1623. {$endif}
  1624. t := context.GetType(PTypeInfo(TypeInfo(TArrayOfLongint2DStatic)));
  1625. Check(t is TRttiArrayType, 'Type is not a TRttiArrayType');
  1626. a := TRttiArrayType(t);
  1627. CheckEquals(2, a.DimensionCount, 'Dimension count does not match');
  1628. CheckEquals(4 * 3, a.TotalElementCount, 'Total element count does not match');
  1629. el := a.ElementType;
  1630. Check(el is TRttiOrdinalType, 'Element type is not a TRttiOrdinalType');
  1631. Check(el = context.GetType(PTypeInfo(TypeInfo(LongInt))), 'Element type is not a LongInt');
  1632. t := a.Dimensions[0];
  1633. {$ifdef fpc}
  1634. Check(t is TRttiOrdinalType, 'Index type is not a TRttiOrdinalType');
  1635. o := TRttiOrdinalType(t);
  1636. { Currently this is a full type :/ }
  1637. {CheckEquals(0, o.MinValue, 'Minimum value of 1st dimension does not match');
  1638. CheckEquals(3, o.MaxValue, 'Maximum value of 1st dimension does not match');}
  1639. {$else}
  1640. Check(t = Nil, 'Index type is not Nil');
  1641. {$endif}
  1642. t := a.Dimensions[1];
  1643. {$ifdef fpc}
  1644. Check(t is TRttiOrdinalType, 'Index type is not a TRttiOrdinalType');
  1645. o := TRttiOrdinalType(t);
  1646. { Currently this is a full type :/ }
  1647. {CheckEquals(2, o.MinValue, 'Minimum value of 1st dimension does not match');
  1648. CheckEquals(4, o.MaxValue, 'Maximum value of 1st dimension does not match');}
  1649. {$else}
  1650. Check(t = Nil, 'Index type is not Nil');
  1651. {$endif}
  1652. finally
  1653. context.Free;
  1654. end;
  1655. end;
  1656. procedure TTestRTTI.TestDynArray;
  1657. var
  1658. context: TRttiContext;
  1659. t, el: TRttiType;
  1660. a: TRttiDynamicArrayType;
  1661. begin
  1662. context := TRttiContext.Create;
  1663. try
  1664. t := context.GetType(PTypeInfo(TypeInfo(TArrayOfLongintDyn)));
  1665. Check(t is TRttiDynamicArrayType, 'Type is not a TRttiDynamicArrayType');
  1666. a := TRttiDynamicArrayType(t);
  1667. CheckEquals('tests.rtti.types', LowerCase(a.DeclaringUnitName), 'Unit type does not match for dynamic array');
  1668. CheckEquals(a.ElementSize, SizeUInt(SizeOf(LongInt)), 'Element size does not match for dynamic array');
  1669. el := a.ElementType;
  1670. Check(el is TRttiOrdinalType, 'Element type is not a TRttiOrdinalType');
  1671. Check(el = context.GetType(PTypeInfo(TypeInfo(LongInt))), 'Element type is not a LongInt');
  1672. { ToDo: check OLE type }
  1673. finally
  1674. context.Free;
  1675. end;
  1676. end;
  1677. procedure TTestRTTI.TestProcVar;
  1678. var
  1679. context: TRttiContext;
  1680. t: TRttiType;
  1681. p: TRttiProcedureType;
  1682. params: {$ifdef fpc}specialize{$endif} TArray<TRttiParameter>;
  1683. begin
  1684. context := TRttiContext.Create;
  1685. try
  1686. t := context.GetType(PTypeInfo(TypeInfo(TTestProc)));
  1687. Check(Assigned(t), 'Rtti Type is Nil');
  1688. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1689. Check(t is TRttiProcedureType, 'Rtti Type is not a procedure type');
  1690. p := t as TRttiProcedureType;
  1691. Check(p.CallingConvention = DefaultCC, 'Calling convention does not match');
  1692. Check(not Assigned(p.ReturnType), 'Return type is assigned');
  1693. CheckEquals(0, Length(p.GetParameters), 'Procedure variable has parameters');
  1694. t := context.GetType(PTypeInfo(TypeInfo(TTestFunc1)));
  1695. Check(Assigned(t), 'Rtti Type is Nil');
  1696. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1697. Check(t is TRttiProcedureType, 'Rtti Type is not a procedure type');
  1698. p := t as TRttiProcedureType;
  1699. Check(p.CallingConvention = DefaultCC, 'Calling convention does not match');
  1700. Check(Assigned(p.ReturnType), 'Return type is not assigned');
  1701. //Check(p.ReturnType is TRttiOrdinalType, 'Return type is not an ordinal type');
  1702. CheckEquals(0, Length(p.GetParameters), 'Procedure variable has parameters');
  1703. t := context.GetType(PTypeInfo(TypeInfo(TTestFunc2)));
  1704. Check(Assigned(t), 'Rtti Type is Nil');
  1705. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1706. Check(t is TRttiProcedureType, 'Rtti Type is not a procedure type');
  1707. p := t as TRttiProcedureType;
  1708. Check(p.CallingConvention = DefaultCC, 'Calling convention does not match');
  1709. Check(Assigned(p.ReturnType), 'Return type is not assigned');
  1710. Check(p.ReturnType is TRttiStringType, 'Return type is not a string type');
  1711. params := p.GetParameters;
  1712. CheckEquals(2, Length(params), 'Procedure variable has incorrect amount of parameters');
  1713. Check(params[0].ParamType.TypeKind in [tkInteger, tkInt64], 'Parameter 1 is not an ordinal type');
  1714. //Check(params[0].ParamType is TRttiOrdinalType, 'Parameter 1 is not an ordinal type');
  1715. Check(pfArray in params[1].Flags, 'Parameter 2 is not an array');
  1716. Check(params[1].ParamType.TypeKind in [tkInteger, tkInt64], 'Parameter 2 is not an ordinal array');
  1717. finally
  1718. context.Free;
  1719. end;
  1720. end;
  1721. procedure TTestRTTI.TestMethod;
  1722. var
  1723. context: TRttiContext;
  1724. t: TRttiType;
  1725. m: TRttiMethodType;
  1726. params: {$ifdef fpc}specialize{$endif} TArray<TRttiParameter>;
  1727. begin
  1728. context := TRttiContext.Create;
  1729. try
  1730. t := context.GetType(PTypeInfo(TypeInfo(TTestMethod)));
  1731. Check(Assigned(t), 'Rtti Type is Nil');
  1732. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1733. Check(t is TRttiMethodType, 'Rtti Type is not a method type');
  1734. m := t as TRttiMethodType;
  1735. Check(m.CallingConvention = DefaultCC, 'Calling convention does not match');
  1736. Check(not Assigned(m.ReturnType), 'Return type is assigned');
  1737. CheckEquals(0, Length(m.GetParameters), 'Method variable has parameters');
  1738. t := context.GetType(PTypeInfo(TypeInfo(TTestMethod1)));
  1739. Check(Assigned(t), 'Rtti Type is Nil');
  1740. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1741. Check(t is TRttiMethodType, 'Rtti Type is not a method type');
  1742. m := t as TRttiMethodType;
  1743. Check(m.CallingConvention = DefaultCC, 'Calling convention does not match');
  1744. Check(Assigned(m.ReturnType), 'Return type is not assigned');
  1745. //Check(p.ReturnType is TRttiOrdinalType, 'Return type is not an ordinal type');
  1746. CheckEquals(0, Length(m.GetParameters), 'Method variable has parameters');
  1747. t := context.GetType(PTypeInfo(TypeInfo(TTestMethod2)));
  1748. Check(Assigned(t), 'Rtti Type is Nil');
  1749. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1750. Check(t is TRttiMethodType, 'Rtti Type is not a method type');
  1751. m := t as TRttiMethodType;
  1752. Check(m.CallingConvention = DefaultCC, 'Calling convention does not match');
  1753. Check(Assigned(m.ReturnType), 'Return type is not assigned');
  1754. Check(m.ReturnType is TRttiStringType, 'Return type is not a string type');
  1755. params := m.GetParameters;
  1756. CheckEquals(2, Length(params), 'Method variable has incorrect amount of parameters');
  1757. Check(params[0].ParamType.TypeKind in [tkInteger, tkInt64], 'Parameter 1 is not an ordinal type');
  1758. //Check(params[0].ParamType is TRttiOrdinalType, 'Parameter 1 is not an ordinal type');
  1759. Check(pfArray in params[1].Flags, 'Parameter 2 is not an array');
  1760. Check(params[1].ParamType.TypeKind in [tkInteger, tkInt64], 'Parameter 2 is not an ordinal array');
  1761. finally
  1762. context.Free;
  1763. end;
  1764. end;
  1765. initialization
  1766. {$ifdef fpc}
  1767. RegisterTest(TTestRTTI);
  1768. {$else fpc}
  1769. RegisterTest(TTestRTTI.Suite);
  1770. {$endif fpc}
  1771. end.