tests.rtti.pas 64 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060
  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. { TTestCase1 }
  17. TTestCase1= 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 TestPropSetValueString;
  34. procedure TestPropSetValueInteger;
  35. procedure TestPropSetValueBoolean;
  36. procedure TestPropSetValueShortString;
  37. procedure TestGetValueStringCastError;
  38. procedure TestGetIsReadable;
  39. procedure TestIsWritable;
  40. procedure TestIsType;
  41. procedure TestMakeNil;
  42. procedure TestMakeObject;
  43. procedure TestMakeArrayDynamic;
  44. procedure TestMakeArrayStatic;
  45. {$ifdef fpc}
  46. procedure TestMakeArrayOpen;
  47. {$endif}
  48. procedure TestMakeSingle;
  49. procedure TestMakeDouble;
  50. procedure TestMakeExtended;
  51. procedure TestMakeCurrency;
  52. procedure TestMakeComp;
  53. procedure TestMakeEnum;
  54. procedure TestMakeAnsiChar;
  55. procedure TestMakeWideChar;
  56. procedure TestFromOrdinal;
  57. procedure TestDataSize;
  58. procedure TestDataSizeEmpty;
  59. procedure TestReferenceRawData;
  60. procedure TestReferenceRawDataEmpty;
  61. procedure TestIsManaged;
  62. {$ifdef fpc}
  63. procedure TestOpenArrayToDyn;
  64. {$endif}
  65. procedure TestInterface;
  66. {$ifdef fpc}
  67. procedure TestInterfaceRaw;
  68. {$endif}
  69. procedure TestProcVar;
  70. procedure TestMethod;
  71. procedure TestRawThunk;
  72. private
  73. procedure MakeFromOrdinalTObject;
  74. procedure MakeFromOrdinalSet;
  75. procedure MakeFromOrdinalString;
  76. procedure MakeFromOrdinalNil;
  77. end;
  78. implementation
  79. uses
  80. Tests.Rtti.Util;
  81. type
  82. {$M+}
  83. TGetClassProperties = class
  84. private
  85. FPubPropRO: integer;
  86. FPubPropRW: integer;
  87. published
  88. property PubPropRO: integer read FPubPropRO;
  89. property PubPropRW: integer read FPubPropRW write FPubPropRW;
  90. property PubPropSetRO: integer read FPubPropRO;
  91. property PubPropSetRW: integer read FPubPropRW write FPubPropRW;
  92. end;
  93. TGetClassPropertiesSub = class(TGetClassProperties)
  94. end;
  95. {$M-}
  96. { TTestValueClass }
  97. {$M+}
  98. TTestValueClass = class
  99. private
  100. FAInteger: integer;
  101. FAString: string;
  102. FABoolean: boolean;
  103. FAShortString: ShortString;
  104. function GetAInteger: integer;
  105. function GetAString: string;
  106. function GetABoolean: boolean;
  107. function GetAShortString: ShortString;
  108. procedure SetWriteOnly(AValue: integer);
  109. published
  110. property AInteger: Integer read FAInteger write FAInteger;
  111. property AString: string read FAString write FAString;
  112. property ABoolean: boolean read FABoolean write FABoolean;
  113. property AShortString: ShortString read FAShortString write FAShortString;
  114. property AGetInteger: Integer read GetAInteger;
  115. property AGetString: string read GetAString;
  116. property AGetBoolean: boolean read GetABoolean;
  117. property AGetShortString: ShortString read GetAShortString;
  118. property AWriteOnly: integer write SetWriteOnly;
  119. end;
  120. {$M-}
  121. {$M+}
  122. ITestInterface = interface
  123. procedure Test;
  124. function Test2: LongInt;
  125. procedure Test3(aArg1: LongInt; const aArg2: AnsiString; var aArg3: Boolean; out aArg4: Word);
  126. function Test4(aArg1: array of LongInt; aArg2: array of const): AnsiString;
  127. end;
  128. {$M-}
  129. TManagedRec = record
  130. s: string;
  131. end;
  132. {$ifdef fpc}
  133. TManagedRecOp = record
  134. class operator AddRef(var a: TManagedRecOp);
  135. end;
  136. {$endif}
  137. TNonManagedRec = record
  138. i: Integer;
  139. end;
  140. TManagedObj = object
  141. i: IInterface;
  142. end;
  143. TNonManagedObj = object
  144. d: double;
  145. end;
  146. TTestEnum = (te1, te2, te3, te4, te5);
  147. TTestSet = set of TTestEnum;
  148. TTestProc = procedure;
  149. TTestFunc1 = function: LongInt;
  150. TTestFunc2 = function(aArg1: LongInt; aArg2: array of LongInt): String;
  151. TTestMethod = procedure of object;
  152. TTestMethod1 = function: LongInt of object;
  153. TTestMethod2 = function(aArg1: LongInt; aArg2: array of LongInt): String of object;
  154. TTestHelper = class helper for TObject
  155. end;
  156. TArrayOfString = array[0..0] of string;
  157. TArrayOfManagedRec = array[0..0] of TManagedRec;
  158. TArrayOfNonManagedRec = array[0..0] of TNonManagedRec;
  159. TArrayOfByte = array[0..0] of byte;
  160. TArrayOfLongintDyn = array of LongInt;
  161. TArrayOfLongintStatic = array[0..3] of LongInt;
  162. TTestRecord = record
  163. Value1: LongInt;
  164. Value2: String;
  165. end;
  166. PTestRecord = ^TTestRecord;
  167. {$ifdef fpc}
  168. {$PUSH}
  169. {$INTERFACES CORBA}
  170. ICORBATest = interface
  171. end;
  172. {$POP}
  173. {$endif}
  174. {$ifdef fpc}
  175. class operator TManagedRecOp.AddRef(var a: TManagedRecOp);
  176. begin
  177. end;
  178. {$endif}
  179. { TTestValueClass }
  180. function TTestValueClass.GetAInteger: integer;
  181. begin
  182. result := FAInteger;
  183. end;
  184. function TTestValueClass.GetAString: string;
  185. begin
  186. result := FAString;
  187. end;
  188. function TTestValueClass.GetABoolean: boolean;
  189. begin
  190. result := FABoolean;
  191. end;
  192. function TTestValueClass.GetAShortString: ShortString;
  193. begin
  194. Result := FAShortString;
  195. end;
  196. procedure TTestValueClass.SetWriteOnly(AValue: integer);
  197. begin
  198. // Do nothing
  199. end;
  200. { Note: GetTypes currently only returns those types that had been acquired using
  201. GetType, so GetTypes itself can't be really tested currently }
  202. (*procedure TTestCase1.GetTypes;
  203. var
  204. LContext: TRttiContext;
  205. LType: TRttiType;
  206. IsTestCaseClassFound: boolean;
  207. begin
  208. LContext := TRttiContext.Create;
  209. { Enumerate all types declared in the application }
  210. for LType in LContext.GetTypes() do
  211. begin
  212. if LType.Name='TTestCase1' then
  213. IsTestCaseClassFound:=true;
  214. end;
  215. LContext.Free;
  216. CheckTrue(IsTestCaseClassFound, 'RTTI information does not contain class of testcase.');
  217. end;*)
  218. procedure TTestCase1.TestGetValueStringCastError;
  219. var
  220. ATestClass : TTestValueClass;
  221. c: TRttiContext;
  222. ARttiType: TRttiType;
  223. AValue: TValue;
  224. i: integer;
  225. HadException: boolean;
  226. begin
  227. c := TRttiContext.Create;
  228. try
  229. ATestClass := TTestValueClass.Create;
  230. ATestClass.AString := '12';
  231. try
  232. ARttiType := c.GetType(ATestClass.ClassInfo);
  233. AValue := ARttiType.GetProperty('astring').GetValue(ATestClass);
  234. HadException := false;
  235. try
  236. i := AValue.AsInteger;
  237. except
  238. on E: Exception do
  239. if E.ClassType=EInvalidCast then
  240. HadException := true;
  241. end;
  242. Check(HadException, 'No or invalid exception on invalid cast');
  243. finally
  244. AtestClass.Free;
  245. end;
  246. finally
  247. c.Free;
  248. end;
  249. end;
  250. procedure TTestCase1.TestMakeNil;
  251. var
  252. value: TValue;
  253. begin
  254. TValue.Make(Nil, Nil, value);
  255. CheckTrue(value.Kind = tkUnknown);
  256. CheckTrue(value.IsEmpty);
  257. CheckTrue(value.IsObject);
  258. CheckTrue(value.IsClass);
  259. CheckTrue(value.IsOrdinal);
  260. CheckFalse(value.IsArray);
  261. CheckTrue(value.AsObject = Nil);
  262. CheckTrue(value.AsClass = Nil);
  263. CheckTrue(value.AsInterface = Nil);
  264. CheckEquals(0, value.AsOrdinal);
  265. TValue.Make(Nil, TypeInfo(TObject), value);
  266. CheckTrue(value.IsEmpty);
  267. CheckTrue(value.IsObject);
  268. CheckTrue(value.IsClass);
  269. CheckTrue(value.IsOrdinal);
  270. CheckFalse(value.IsArray);
  271. CheckTrue(value.AsObject=Nil);
  272. CheckTrue(value.AsClass=Nil);
  273. CheckTrue(value.AsInterface=Nil);
  274. CheckEquals(0, value.AsOrdinal);
  275. TValue.Make(Nil, TypeInfo(TClass), value);
  276. CheckTrue(value.IsEmpty);
  277. CheckTrue(value.IsClass);
  278. CheckTrue(value.IsOrdinal);
  279. CheckFalse(value.IsArray);
  280. CheckTrue(value.AsObject=Nil);
  281. CheckTrue(value.AsClass=Nil);
  282. CheckTrue(value.AsInterface=Nil);
  283. CheckEquals(0, value.AsOrdinal);
  284. TValue.Make(Nil, TypeInfo(LongInt), value);
  285. CheckTrue(value.IsOrdinal);
  286. CheckFalse(value.IsEmpty);
  287. CheckFalse(value.IsClass);
  288. CheckFalse(value.IsObject);
  289. CheckFalse(value.IsArray);
  290. CheckEquals(0, value.AsOrdinal);
  291. CheckEquals(0, value.AsInteger);
  292. CheckEquals(0, value.AsInt64);
  293. CheckEquals(0, value.AsUInt64);
  294. TValue.Make(Nil, TypeInfo(String), value);
  295. CheckFalse(value.IsEmpty);
  296. CheckFalse(value.IsObject);
  297. CheckFalse(value.IsClass);
  298. CheckFalse(value.IsArray);
  299. CheckEquals('', value.AsString);
  300. end;
  301. procedure TTestCase1.TestMakeObject;
  302. var
  303. AValue: TValue;
  304. ATestClass: TTestValueClass;
  305. begin
  306. ATestClass := TTestValueClass.Create;
  307. ATestClass.AInteger := 54329;
  308. TValue.Make(@ATestClass, TypeInfo(TTestValueClass),AValue);
  309. CheckEquals(AValue.IsClass, False);
  310. CheckEquals(AValue.IsObject, True);
  311. Check(AValue.AsObject=ATestClass);
  312. Check(PPointer(AValue.GetReferenceToRawData)^ = Pointer(ATestClass));
  313. CheckEquals(TTestValueClass(AValue.AsObject).AInteger, 54329);
  314. ATestClass.Free;
  315. end;
  316. procedure TTestCase1.TestMakeArrayDynamic;
  317. var
  318. arr: TArrayOfLongintDyn;
  319. value: TValue;
  320. begin
  321. SetLength(arr, 2);
  322. arr[0] := 42;
  323. arr[1] := 21;
  324. TValue.Make(@arr, TypeInfo(TArrayOfLongintDyn), value);
  325. CheckEquals(value.IsArray, True);
  326. CheckEquals(value.IsObject, False);
  327. CheckEquals(value.IsOrdinal, False);
  328. CheckEquals(value.IsClass, False);
  329. CheckEquals(value.GetArrayLength, 2);
  330. CheckEquals(value.GetArrayElement(0).AsInteger, 42);
  331. CheckEquals(value.GetArrayElement(1).AsInteger, 21);
  332. Check(PPointer(value.GetReferenceToRawData)^ = Pointer(arr));
  333. value.SetArrayElement(0, 84);
  334. CheckEquals(arr[0], 84);
  335. end;
  336. procedure TTestCase1.TestMakeArrayStatic;
  337. type
  338. TArrStat = array[0..1] of LongInt;
  339. TArrStat2D = array[0..1, 0..1] of LongInt;
  340. var
  341. arr: TArrStat;
  342. arr2D: TArrStat2D;
  343. value: TValue;
  344. begin
  345. arr[0] := 42;
  346. arr[1] := 21;
  347. TValue.Make(@arr, TypeInfo(TArrStat), value);
  348. CheckEquals(value.IsArray, True);
  349. CheckEquals(value.IsObject, False);
  350. CheckEquals(value.IsOrdinal, False);
  351. CheckEquals(value.IsClass, False);
  352. CheckEquals(value.GetArrayLength, 2);
  353. CheckEquals(value.GetArrayElement(0).AsInteger, 42);
  354. CheckEquals(value.GetArrayElement(1).AsInteger, 21);
  355. value.SetArrayElement(0, 84);
  356. { since this is a static array the original array isn't touched! }
  357. CheckEquals(arr[0], 42);
  358. arr2D[0, 0] := 42;
  359. arr2D[0, 1] := 21;
  360. arr2D[1, 0] := 84;
  361. arr2D[1, 1] := 63;
  362. TValue.Make(@arr2D, TypeInfo(TArrStat2D), value);
  363. CheckEquals(value.IsArray, True);
  364. CheckEquals(value.GetArrayLength, 4);
  365. CheckEquals(value.GetArrayElement(0).AsInteger, 42);
  366. CheckEquals(value.GetArrayElement(1).AsInteger, 21);
  367. CheckEquals(value.GetArrayElement(2).AsInteger, 84);
  368. CheckEquals(value.GetArrayElement(3).AsInteger, 63);
  369. end;
  370. {$ifdef fpc}
  371. procedure TTestCase1.TestMakeArrayOpen;
  372. procedure TestOpenArrayValueCopy(aArr: array of LongInt);
  373. var
  374. value: TValue;
  375. begin
  376. TValue.MakeOpenArray(@aArr[0], Length(aArr), PTypeInfo(TypeInfo(aArr)), value);
  377. CheckEquals(value.IsArray, True);
  378. CheckEquals(value.IsOpenArray, True);
  379. CheckEquals(value.IsObject, False);
  380. CheckEquals(value.IsOrdinal, False);
  381. CheckEquals(value.IsClass, False);
  382. CheckEquals(value.GetArrayLength, 2);
  383. CheckEquals(value.GetArrayElement(0).AsInteger, 42);
  384. CheckEquals(value.GetArrayElement(1).AsInteger, 21);
  385. value.SetArrayElement(0, 84);
  386. { since this is an open array the original array is modified! }
  387. CheckEquals(aArr[0], 84);
  388. end;
  389. procedure TestOpenArrayValueVar(var aArr: array of LongInt);
  390. var
  391. value: TValue;
  392. begin
  393. TValue.MakeOpenArray(@aArr[0], Length(aArr), PTypeInfo(TypeInfo(aArr)), value);
  394. CheckEquals(value.IsArray, True);
  395. CheckEquals(value.IsOpenArray, True);
  396. CheckEquals(value.IsObject, False);
  397. CheckEquals(value.IsOrdinal, False);
  398. CheckEquals(value.IsClass, False);
  399. CheckEquals(value.GetArrayLength, 2);
  400. CheckEquals(value.GetArrayElement(0).AsInteger, 42);
  401. CheckEquals(value.GetArrayElement(1).AsInteger, 21);
  402. value.SetArrayElement(0, 84);
  403. { since this is an open array the original array is modified! }
  404. CheckEquals(aArr[0], 84);
  405. end;
  406. procedure TestOpenArrayValueOut(var aArr: array of LongInt);
  407. var
  408. value: TValue;
  409. begin
  410. TValue.MakeOpenArray(@aArr[0], Length(aArr), PTypeInfo(TypeInfo(aArr)), value);
  411. CheckEquals(value.IsArray, True);
  412. CheckEquals(value.IsOpenArray, True);
  413. CheckEquals(value.IsObject, False);
  414. CheckEquals(value.IsOrdinal, False);
  415. CheckEquals(value.IsClass, False);
  416. CheckEquals(value.GetArrayLength, 2);
  417. CheckEquals(value.GetArrayElement(0).AsInteger, 42);
  418. CheckEquals(value.GetArrayElement(1).AsInteger, 21);
  419. value.SetArrayElement(0, 84);
  420. value.SetArrayElement(1, 128);
  421. { since this is an open array the original array is modified! }
  422. CheckEquals(aArr[0], 84);
  423. CheckEquals(aArr[1], 128);
  424. CheckEquals(value.GetArrayElement(0).AsInteger, 84);
  425. CheckEquals(value.GetArrayElement(1).AsInteger, 128);
  426. end;
  427. var
  428. arr: array of LongInt;
  429. begin
  430. TestOpenArrayValueCopy([42, 21]);
  431. arr := [42, 21];
  432. TestOpenArrayValueVar(arr);
  433. CheckEquals(arr[0], 84);
  434. CheckEquals(arr[1], 21);
  435. arr := [42, 21];
  436. TestOpenArrayValueOut(arr);
  437. CheckEquals(arr[0], 84);
  438. CheckEquals(arr[1], 128);
  439. end;
  440. {$endif}
  441. procedure TTestCase1.TestMakeSingle;
  442. var
  443. fs: Single;
  444. v: TValue;
  445. hadexcept: Boolean;
  446. begin
  447. fs := 3.14;
  448. TValue.Make(@fs, TypeInfo(fs), v);
  449. CheckEquals(v.IsClass, False);
  450. CheckEquals(v.IsObject, False);
  451. CheckEquals(v.IsOrdinal, False);
  452. Check(v.AsExtended=fs);
  453. Check(v.GetReferenceToRawData <> @fs);
  454. try
  455. hadexcept := False;
  456. v.AsInt64;
  457. except
  458. hadexcept := True;
  459. end;
  460. CheckTrue(hadexcept, 'No signed type conversion exception');
  461. try
  462. hadexcept := False;
  463. v.AsUInt64;
  464. except
  465. hadexcept := True;
  466. end;
  467. CheckTrue(hadexcept, 'No unsigned type conversion exception');
  468. end;
  469. procedure TTestCase1.TestMakeDouble;
  470. var
  471. fd: Double;
  472. v: TValue;
  473. hadexcept: Boolean;
  474. begin
  475. fd := 3.14;
  476. TValue.Make(@fd, TypeInfo(fd), v);
  477. CheckEquals(v.IsClass, False);
  478. CheckEquals(v.IsObject, False);
  479. CheckEquals(v.IsOrdinal, False);
  480. Check(v.AsExtended=fd);
  481. Check(v.GetReferenceToRawData <> @fd);
  482. try
  483. hadexcept := False;
  484. v.AsInt64;
  485. except
  486. hadexcept := True;
  487. end;
  488. CheckTrue(hadexcept, 'No signed type conversion exception');
  489. try
  490. hadexcept := False;
  491. v.AsUInt64;
  492. except
  493. hadexcept := True;
  494. end;
  495. CheckTrue(hadexcept, 'No unsigned type conversion exception');
  496. end;
  497. procedure TTestCase1.TestMakeExtended;
  498. var
  499. fe: Extended;
  500. v: TValue;
  501. hadexcept: Boolean;
  502. begin
  503. fe := 3.14;
  504. TValue.Make(@fe, TypeInfo(fe), v);
  505. CheckEquals(v.IsClass, False);
  506. CheckEquals(v.IsObject, False);
  507. CheckEquals(v.IsOrdinal, False);
  508. Check(v.AsExtended=fe);
  509. Check(v.GetReferenceToRawData <> @fe);
  510. try
  511. hadexcept := False;
  512. v.AsInt64;
  513. except
  514. hadexcept := True;
  515. end;
  516. CheckTrue(hadexcept, 'No signed type conversion exception');
  517. try
  518. hadexcept := False;
  519. v.AsUInt64;
  520. except
  521. hadexcept := True;
  522. end;
  523. CheckTrue(hadexcept, 'No unsigned type conversion exception');
  524. end;
  525. procedure TTestCase1.TestMakeCurrency;
  526. var
  527. fcu: Currency;
  528. v: TValue;
  529. hadexcept: Boolean;
  530. begin
  531. fcu := 3.14;
  532. TValue.Make(@fcu, TypeInfo(fcu), v);
  533. CheckEquals(v.IsClass, False);
  534. CheckEquals(v.IsObject, False);
  535. CheckEquals(v.IsOrdinal, False);
  536. Check(v.AsExtended=Extended(fcu));
  537. Check(v.AsCurrency=fcu);
  538. Check(v.GetReferenceToRawData <> @fcu);
  539. try
  540. hadexcept := False;
  541. v.AsInt64;
  542. except
  543. hadexcept := True;
  544. end;
  545. CheckTrue(hadexcept, 'No signed type conversion exception');
  546. try
  547. hadexcept := False;
  548. v.AsUInt64;
  549. except
  550. hadexcept := True;
  551. end;
  552. CheckTrue(hadexcept, 'No unsigned type conversion exception');
  553. end;
  554. procedure TTestCase1.TestMakeComp;
  555. var
  556. fco: Comp;
  557. v: TValue;
  558. hadexcept: Boolean;
  559. begin
  560. fco := 314;
  561. TValue.Make(@fco, TypeInfo(fco), v);
  562. if v.Kind <> tkFloat then
  563. Exit;
  564. CheckEquals(v.IsClass, False);
  565. CheckEquals(v.IsObject, False);
  566. CheckEquals(v.IsOrdinal, False);
  567. Check(v.AsExtended=Extended(fco));
  568. Check(v.GetReferenceToRawData <> @fco);
  569. try
  570. hadexcept := False;
  571. CheckEquals(v.AsInt64, 314);
  572. except
  573. hadexcept := True;
  574. end;
  575. CheckFalse(hadexcept, 'Had signed type conversion exception');
  576. try
  577. hadexcept := False;
  578. CheckEquals(v.AsUInt64, 314);
  579. except
  580. hadexcept := True;
  581. end;
  582. CheckFalse(hadexcept, 'Had unsigned type conversion exception');
  583. end;
  584. procedure TTestCase1.TestMakeEnum;
  585. var
  586. e: TTestEnum;
  587. v: TValue;
  588. begin
  589. e := te1;
  590. TValue.Make(@e, TypeInfo(e), v);
  591. Check(not v.IsClass);
  592. Check(not v.IsArray);
  593. Check(not v.IsEmpty);
  594. Check(not v.IsOpenArray);
  595. Check(not v.IsObject);
  596. Check(v.IsOrdinal);
  597. Check(v.GetReferenceToRawData <> @e);
  598. Check(TTestEnum(v.AsOrdinal) = te1);
  599. end;
  600. procedure TTestCase1.TestMakeAnsiChar;
  601. var
  602. c: AnsiChar;
  603. v: TValue;
  604. begin
  605. c := #20;
  606. TValue.Make(@c, TypeInfo(c), v);
  607. Check(not v.IsClass);
  608. Check(not v.IsArray);
  609. Check(not v.IsEmpty);
  610. Check(not v.IsOpenArray);
  611. Check(not v.IsObject);
  612. Check(v.IsOrdinal);
  613. Check(v.GetReferenceToRawData <> @c);
  614. Check(AnsiChar(v.AsOrdinal) = #20);
  615. end;
  616. procedure TTestCase1.TestMakeWideChar;
  617. var
  618. c: WideChar;
  619. v: TValue;
  620. begin
  621. c := #$1234;
  622. TValue.Make(@c, TypeInfo(c), v);
  623. Check(not v.IsClass);
  624. Check(not v.IsArray);
  625. Check(not v.IsEmpty);
  626. Check(not v.IsOpenArray);
  627. Check(not v.IsObject);
  628. Check(v.IsOrdinal);
  629. Check(v.GetReferenceToRawData <> @c);
  630. Check(WideChar(v.AsOrdinal) = #$1234);
  631. end;
  632. procedure TTestCase1.MakeFromOrdinalTObject;
  633. begin
  634. TValue.FromOrdinal(TypeInfo(TObject), 42);
  635. end;
  636. procedure TTestCase1.MakeFromOrdinalSet;
  637. begin
  638. TValue.FromOrdinal(TypeInfo(TTestSet), 42);
  639. end;
  640. procedure TTestCase1.MakeFromOrdinalString;
  641. begin
  642. TValue.FromOrdinal(TypeInfo(AnsiString), 42);
  643. end;
  644. procedure TTestCase1.MakeFromOrdinalNil;
  645. begin
  646. TValue.FromOrdinal(Nil, 42);
  647. end;
  648. procedure TTestCase1.TestFromOrdinal;
  649. var
  650. v: TValue;
  651. begin
  652. v := TValue.FromOrdinal(TypeInfo(LongInt), 42);
  653. Check(v.IsOrdinal);
  654. CheckEquals(v.AsOrdinal, 42);
  655. v := TValue.FromOrdinal(TypeInfo(Boolean), Ord(True));
  656. Check(v.IsOrdinal);
  657. CheckEquals(v.AsOrdinal, Ord(True));
  658. v := TValue.FromOrdinal(TypeInfo(Int64), $1234123412341234);
  659. Check(v.IsOrdinal);
  660. CheckEquals(v.AsOrdinal, $1234123412341234);
  661. v := TValue.FromOrdinal(TypeInfo(QWord), $1234123412341234);
  662. Check(v.IsOrdinal);
  663. CheckEquals(v.AsOrdinal, $1234123412341234);
  664. v := TValue.FromOrdinal(TypeInfo(LongBool), Ord(True));
  665. Check(v.IsOrdinal);
  666. CheckEquals(v.AsOrdinal, Ord(True));
  667. v := TValue.FromOrdinal(TypeInfo(TTestEnum), Ord(te1));
  668. Check(v.IsOrdinal);
  669. CheckEquals(v.AsOrdinal, Ord(te1));
  670. v := TValue.FromOrdinal(TypeInfo(AnsiChar), Ord(#20));
  671. Check(v.IsOrdinal);
  672. CheckEquals(v.AsOrdinal, Ord(#20));
  673. v := TValue.FromOrdinal(TypeInfo(WideChar), Ord(#$1234));
  674. Check(v.IsOrdinal);
  675. CheckEquals(v.AsOrdinal, Ord(#$1234));
  676. CheckException({$ifdef fpc}@{$endif}MakeFromOrdinalNil, EInvalidCast);
  677. CheckException({$ifdef fpc}@{$endif}MakeFromOrdinalTObject, EInvalidCast);
  678. CheckException({$ifdef fpc}@{$endif}MakeFromOrdinalSet, EInvalidCast);
  679. CheckException({$ifdef fpc}@{$endif}MakeFromOrdinalString, EInvalidCast);
  680. end;
  681. procedure TTestCase1.TestGetIsReadable;
  682. var
  683. c: TRttiContext;
  684. ARttiType: TRttiType;
  685. AProperty: TRttiProperty;
  686. begin
  687. c := TRttiContext.Create;
  688. try
  689. ARttiType := c.GetType(TTestValueClass);
  690. AProperty := ARttiType.GetProperty('aBoolean');
  691. CheckEquals(AProperty.IsReadable, true);
  692. AProperty := ARttiType.GetProperty('aGetBoolean');
  693. CheckEquals(AProperty.IsReadable, true);
  694. AProperty := ARttiType.GetProperty('aWriteOnly');
  695. CheckEquals(AProperty.IsReadable, False);
  696. finally
  697. c.Free;
  698. end;
  699. end;
  700. procedure TTestCase1.TestIsWritable;
  701. var
  702. c: TRttiContext;
  703. ARttiType: TRttiType;
  704. AProperty: TRttiProperty;
  705. begin
  706. c := TRttiContext.Create;
  707. try
  708. ARttiType := c.GetType(TTestValueClass);
  709. AProperty := ARttiType.GetProperty('aBoolean');
  710. CheckEquals(AProperty.IsWritable, true);
  711. AProperty := ARttiType.GetProperty('aGetBoolean');
  712. CheckEquals(AProperty.IsWritable, false);
  713. AProperty := ARttiType.GetProperty('aWriteOnly');
  714. CheckEquals(AProperty.IsWritable, True);
  715. finally
  716. c.Free;
  717. end;
  718. end;
  719. procedure TTestCase1.TestIsType;
  720. type
  721. TMyLongInt = type LongInt;
  722. var
  723. v: TValue;
  724. l: LongInt;
  725. ml: TMyLongInt;
  726. begin
  727. l := 42;
  728. ml := 42;
  729. TValue.Make(@l, TypeInfo(l), v);
  730. Check(v.IsType(TypeInfo(l)));
  731. Check(not v.IsType(TypeInfo(ml)));
  732. Check(not v.IsType(TypeInfo(String)));
  733. Check(v.specialize IsType<LongInt>);
  734. Check(not v.specialize IsType<TMyLongInt>);
  735. Check(not v.specialize IsType<String>);
  736. TValue.Make(@ml, TypeInfo(ml), v);
  737. Check(v.IsType(TypeInfo(ml)));
  738. Check(not v.IsType(TypeInfo(l)));
  739. Check(not v.IsType(TypeInfo(String)));
  740. Check(v.specialize IsType<TMyLongInt>);
  741. Check(not v.specialize IsType<LongInt>);
  742. Check(not v.specialize IsType<String>);
  743. end;
  744. procedure TTestCase1.TestPropGetValueBoolean;
  745. var
  746. ATestClass : TTestValueClass;
  747. c: TRttiContext;
  748. ARttiType: TRttiType;
  749. AProperty: TRttiProperty;
  750. AValue: TValue;
  751. begin
  752. c := TRttiContext.Create;
  753. try
  754. ATestClass := TTestValueClass.Create;
  755. ATestClass.ABoolean := true;
  756. try
  757. ARttiType := c.GetType(ATestClass.ClassInfo);
  758. Check(assigned(ARttiType));
  759. AProperty := ARttiType.GetProperty('aBoolean');
  760. AValue := AProperty.GetValue(ATestClass);
  761. CheckEquals(true,AValue.AsBoolean);
  762. ATestClass.ABoolean := false;
  763. CheckEquals(true, AValue.AsBoolean);
  764. CheckEquals('True', AValue.ToString);
  765. CheckEquals(True, AValue.IsOrdinal);
  766. CheckEquals(1, AValue.AsOrdinal);
  767. finally
  768. AtestClass.Free;
  769. end;
  770. CheckEquals(True,AValue.AsBoolean);
  771. finally
  772. c.Free;
  773. end;
  774. end;
  775. procedure TTestCase1.TestPropGetValueShortString;
  776. var
  777. ATestClass : TTestValueClass;
  778. c: TRttiContext;
  779. ARttiType: TRttiType;
  780. AProperty: TRttiProperty;
  781. AValue: TValue;
  782. begin
  783. c := TRttiContext.Create;
  784. try
  785. ATestClass := TTestValueClass.Create;
  786. ATestClass.AShortString := 'Hello World';
  787. try
  788. ARttiType := c.GetType(ATestClass.ClassInfo);
  789. Check(assigned(ARttiType));
  790. AProperty := ARttiType.GetProperty('aShortString');
  791. AValue := AProperty.GetValue(ATestClass);
  792. CheckEquals('Hello World',AValue.AsString);
  793. ATestClass.AShortString := 'Foobar';
  794. CheckEquals('Hello World', AValue.AsString);
  795. CheckEquals(False, AValue.IsOrdinal);
  796. CheckEquals(False, AValue.IsObject);
  797. CheckEquals(False, AValue.IsArray);
  798. CheckEquals(False, AValue.IsClass);
  799. finally
  800. AtestClass.Free;
  801. end;
  802. CheckEquals('Hello World',AValue.AsString);
  803. finally
  804. c.Free;
  805. end;
  806. end;
  807. procedure TTestCase1.TestPropGetValueInteger;
  808. var
  809. ATestClass : TTestValueClass;
  810. c: TRttiContext;
  811. ARttiType: TRttiType;
  812. AProperty: TRttiProperty;
  813. AValue: TValue;
  814. begin
  815. c := TRttiContext.Create;
  816. try
  817. ATestClass := TTestValueClass.Create;
  818. ATestClass.AInteger := 472349;
  819. try
  820. ARttiType := c.GetType(ATestClass.ClassInfo);
  821. Check(assigned(ARttiType));
  822. AProperty := ARttiType.GetProperty('ainteger');
  823. AValue := AProperty.GetValue(ATestClass);
  824. CheckEquals(472349,AValue.AsInteger);
  825. ATestClass.AInteger := 12;
  826. CheckEquals(472349, AValue.AsInteger);
  827. CheckEquals('472349', AValue.ToString);
  828. CheckEquals(True, AValue.IsOrdinal);
  829. finally
  830. AtestClass.Free;
  831. end;
  832. CheckEquals(472349,AValue.AsInteger);
  833. finally
  834. c.Free;
  835. end;
  836. end;
  837. procedure TTestCase1.TestPropGetValueString;
  838. var
  839. ATestClass : TTestValueClass;
  840. c: TRttiContext;
  841. ARttiType: TRttiType;
  842. AProperty: TRttiProperty;
  843. AValue: TValue;
  844. i: int64;
  845. begin
  846. c := TRttiContext.Create;
  847. try
  848. ATestClass := TTestValueClass.Create;
  849. ATestClass.AString := 'Hello World';
  850. try
  851. ARttiType := c.GetType(ATestClass.ClassInfo);
  852. Check(assigned(ARttiType));
  853. AProperty := ARttiType.GetProperty('astring');
  854. AValue := AProperty.GetValue(ATestClass);
  855. CheckEquals('Hello World',AValue.AsString);
  856. ATestClass.AString := 'Goodbye World';
  857. CheckEquals('Hello World',AValue.AsString);
  858. CheckEquals('Hello World',AValue.ToString);
  859. Check(TypeInfo(string)=AValue.TypeInfo);
  860. Check(AValue.TypeData=GetTypeData(AValue.TypeInfo));
  861. Check(AValue.IsEmpty=false);
  862. Check(AValue.IsObject=false);
  863. Check(AValue.IsClass=false);
  864. CheckEquals(AValue.IsOrdinal, false);
  865. CheckEquals(AValue.TryAsOrdinal(i), false);
  866. CheckEquals(AValue.IsType(TypeInfo(string)), true);
  867. CheckEquals(AValue.IsType(TypeInfo(integer)), false);
  868. CheckEquals(AValue.IsArray, false);
  869. finally
  870. AtestClass.Free;
  871. end;
  872. CheckEquals('Hello World',AValue.AsString);
  873. finally
  874. c.Free;
  875. end;
  876. end;
  877. procedure TTestCase1.TestPropGetValueProcBoolean;
  878. var
  879. ATestClass : TTestValueClass;
  880. c: TRttiContext;
  881. ARttiType: TRttiType;
  882. AProperty: TRttiProperty;
  883. AValue: TValue;
  884. begin
  885. c := TRttiContext.Create;
  886. try
  887. ATestClass := TTestValueClass.Create;
  888. ATestClass.ABoolean := true;
  889. try
  890. ARttiType := c.GetType(ATestClass.ClassInfo);
  891. Check(assigned(ARttiType));
  892. AProperty := ARttiType.GetProperty('aGetBoolean');
  893. AValue := AProperty.GetValue(ATestClass);
  894. CheckEquals(true,AValue.AsBoolean);
  895. finally
  896. AtestClass.Free;
  897. end;
  898. CheckEquals(True,AValue.AsBoolean);
  899. finally
  900. c.Free;
  901. end;
  902. end;
  903. procedure TTestCase1.TestPropGetValueProcShortString;
  904. var
  905. ATestClass : TTestValueClass;
  906. c: TRttiContext;
  907. ARttiType: TRttiType;
  908. AProperty: TRttiProperty;
  909. AValue: TValue;
  910. begin
  911. c := TRttiContext.Create;
  912. try
  913. ATestClass := TTestValueClass.Create;
  914. ATestClass.AShortString := 'Hello World';
  915. try
  916. ARttiType := c.GetType(ATestClass.ClassInfo);
  917. Check(assigned(ARttiType));
  918. AProperty := ARttiType.GetProperty('aGetShortString');
  919. AValue := AProperty.GetValue(ATestClass);
  920. CheckEquals('Hello World',AValue.AsString);
  921. finally
  922. AtestClass.Free;
  923. end;
  924. CheckEquals('Hello World',AValue.AsString);
  925. finally
  926. c.Free;
  927. end;
  928. end;
  929. procedure TTestCase1.TestPropSetValueString;
  930. var
  931. ATestClass : TTestValueClass;
  932. c: TRttiContext;
  933. ARttiType: TRttiType;
  934. AProperty: TRttiProperty;
  935. AValue: TValue;
  936. s: string;
  937. begin
  938. c := TRttiContext.Create;
  939. try
  940. ATestClass := TTestValueClass.Create;
  941. try
  942. ARttiType := c.GetType(ATestClass.ClassInfo);
  943. AProperty := ARttiType.GetProperty('astring');
  944. s := 'ipse lorem or something like that';
  945. TValue.Make(@s, TypeInfo(string), AValue);
  946. AProperty.SetValue(ATestClass, AValue);
  947. CheckEquals(ATestClass.AString, s);
  948. s := 'Another string';
  949. CheckEquals(ATestClass.AString, 'ipse lorem or something like that');
  950. finally
  951. AtestClass.Free;
  952. end;
  953. finally
  954. c.Free;
  955. end;
  956. end;
  957. procedure TTestCase1.TestPropSetValueInteger;
  958. var
  959. ATestClass : TTestValueClass;
  960. c: TRttiContext;
  961. ARttiType: TRttiType;
  962. AProperty: TRttiProperty;
  963. AValue: TValue;
  964. i: integer;
  965. begin
  966. c := TRttiContext.Create;
  967. try
  968. ATestClass := TTestValueClass.Create;
  969. try
  970. ARttiType := c.GetType(ATestClass.ClassInfo);
  971. AProperty := ARttiType.GetProperty('aInteger');
  972. i := -43573;
  973. TValue.Make(@i, TypeInfo(Integer), AValue);
  974. AProperty.SetValue(ATestClass, AValue);
  975. CheckEquals(ATestClass.AInteger, i);
  976. i := 1;
  977. CheckEquals(ATestClass.AInteger, -43573);
  978. finally
  979. AtestClass.Free;
  980. end;
  981. finally
  982. c.Free;
  983. end;
  984. end;
  985. procedure TTestCase1.TestPropSetValueBoolean;
  986. var
  987. ATestClass : TTestValueClass;
  988. c: TRttiContext;
  989. ARttiType: TRttiType;
  990. AProperty: TRttiProperty;
  991. AValue: TValue;
  992. b: boolean;
  993. begin
  994. c := TRttiContext.Create;
  995. try
  996. ATestClass := TTestValueClass.Create;
  997. try
  998. ARttiType := c.GetType(ATestClass.ClassInfo);
  999. AProperty := ARttiType.GetProperty('aboolean');
  1000. b := true;
  1001. TValue.Make(@b, TypeInfo(Boolean), AValue);
  1002. AProperty.SetValue(ATestClass, AValue);
  1003. CheckEquals(ATestClass.ABoolean, b);
  1004. b := false;
  1005. CheckEquals(ATestClass.ABoolean, true);
  1006. TValue.Make(@b, TypeInfo(Boolean), AValue);
  1007. AProperty.SetValue(ATestClass, AValue);
  1008. CheckEquals(ATestClass.ABoolean, false);
  1009. finally
  1010. AtestClass.Free;
  1011. end;
  1012. finally
  1013. c.Free;
  1014. end;
  1015. end;
  1016. procedure TTestCase1.TestPropSetValueShortString;
  1017. var
  1018. ATestClass : TTestValueClass;
  1019. c: TRttiContext;
  1020. ARttiType: TRttiType;
  1021. AProperty: TRttiProperty;
  1022. AValue: TValue;
  1023. s: string;
  1024. ss: ShortString;
  1025. begin
  1026. c := TRttiContext.Create;
  1027. try
  1028. ATestClass := TTestValueClass.Create;
  1029. try
  1030. ARttiType := c.GetType(ATestClass.ClassInfo);
  1031. AProperty := ARttiType.GetProperty('aShortString');
  1032. s := 'ipse lorem or something like that';
  1033. TValue.Make(@s, TypeInfo(String), AValue);
  1034. AProperty.SetValue(ATestClass, AValue);
  1035. CheckEquals(ATestClass.AShortString, s);
  1036. s := 'Another string';
  1037. CheckEquals(ATestClass.AShortString, 'ipse lorem or something like that');
  1038. ss := 'Hello World';
  1039. TValue.Make(@ss, TypeInfo(ShortString), AValue);
  1040. AProperty.SetValue(ATestClass, AValue);
  1041. CheckEquals(ATestClass.AShortString, ss);
  1042. ss := 'Foobar';
  1043. CheckEquals(ATestClass.AShortString, 'Hello World');
  1044. finally
  1045. AtestClass.Free;
  1046. end;
  1047. finally
  1048. c.Free;
  1049. end;
  1050. end;
  1051. procedure TTestCase1.TestPropGetValueProcInteger;
  1052. var
  1053. ATestClass : TTestValueClass;
  1054. c: TRttiContext;
  1055. ARttiType: TRttiType;
  1056. AProperty: TRttiProperty;
  1057. AValue: TValue;
  1058. begin
  1059. c := TRttiContext.Create;
  1060. try
  1061. ATestClass := TTestValueClass.Create;
  1062. ATestClass.AInteger := 472349;
  1063. try
  1064. ARttiType := c.GetType(ATestClass.ClassInfo);
  1065. Check(assigned(ARttiType));
  1066. AProperty := ARttiType.GetProperty('agetinteger');
  1067. AValue := AProperty.GetValue(ATestClass);
  1068. CheckEquals(472349,AValue.AsInteger);
  1069. finally
  1070. AtestClass.Free;
  1071. end;
  1072. CheckEquals(472349,AValue.AsInteger);
  1073. finally
  1074. c.Free;
  1075. end;
  1076. end;
  1077. procedure TTestCase1.TestPropGetValueProcString;
  1078. var
  1079. ATestClass : TTestValueClass;
  1080. c: TRttiContext;
  1081. ARttiType: TRttiType;
  1082. AProperty: TRttiProperty;
  1083. AValue: TValue;
  1084. begin
  1085. c := TRttiContext.Create;
  1086. try
  1087. ATestClass := TTestValueClass.Create;
  1088. ATestClass.AString := 'Hello World';
  1089. try
  1090. ARttiType := c.GetType(ATestClass.ClassInfo);
  1091. Check(assigned(ARttiType));
  1092. AProperty := ARttiType.GetProperty('agetstring');
  1093. AValue := AProperty.GetValue(ATestClass);
  1094. CheckEquals('Hello World',AValue.AsString);
  1095. finally
  1096. AtestClass.Free;
  1097. end;
  1098. CheckEquals('Hello World',AValue.AsString);
  1099. finally
  1100. c.Free;
  1101. end;
  1102. end;
  1103. procedure TTestCase1.TestTRttiTypeProperties;
  1104. var
  1105. c: TRttiContext;
  1106. ARttiType: TRttiType;
  1107. begin
  1108. c := TRttiContext.Create;
  1109. try
  1110. ARttiType := c.GetType(TTestValueClass);
  1111. Check(assigned(ARttiType));
  1112. CheckEquals(ARttiType.Name,'TTestValueClass');
  1113. Check(ARttiType.TypeKind=tkClass);
  1114. // CheckEquals(ARttiType.IsPublicType,false);
  1115. CheckEquals(ARttiType.TypeSize,SizeOf(TObject));
  1116. CheckEquals(ARttiType.IsManaged,false);
  1117. CheckEquals(ARttiType.BaseType.classname,'TRttiInstanceType');
  1118. CheckEquals(ARttiType.IsInstance,True);
  1119. CheckEquals(ARttiType.AsInstance.DeclaringUnitName,'tests.rtti');
  1120. Check(ARttiType.BaseType.Name='TObject');
  1121. Check(ARttiType.AsInstance.BaseType.Name='TObject');
  1122. CheckEquals(ARttiType.IsOrdinal,False);
  1123. CheckEquals(ARttiType.IsRecord,False);
  1124. CheckEquals(ARttiType.IsSet,False);
  1125. finally
  1126. c.Free;
  1127. end;
  1128. end;
  1129. procedure TTestCase1.GetTypeInteger;
  1130. var
  1131. LContext: TRttiContext;
  1132. LType: TRttiType;
  1133. begin
  1134. LContext := TRttiContext.Create;
  1135. LType := LContext.GetType(TypeInfo(integer));
  1136. {$ifdef fpc}
  1137. CheckEquals(LType.Name, 'LongInt');
  1138. {$else}
  1139. CheckEquals(LType.Name, 'Integer');
  1140. {$endif}
  1141. LContext.Free;
  1142. end;
  1143. procedure TTestCase1.GetTypePointer;
  1144. var
  1145. context: TRttiContext;
  1146. t: TRttiType;
  1147. p: TRttiPointerType absolute t;
  1148. begin
  1149. context := TRttiContext.Create;
  1150. try
  1151. t := context.GetType(TypeInfo(Pointer));
  1152. Assert(t is TRttiPointerType, 'Type of Pointer is not a TRttiPointerType');
  1153. Assert(not Assigned(p.ReferredType), 'ReferredType of Pointer is not Nil');
  1154. t := context.GetType(TypeInfo(PLongInt));
  1155. Assert(t is TRttiPointerType, 'Type of Pointer is not a TRttiPointerType');
  1156. Assert(Assigned(p.ReferredType), 'ReferredType of PLongInt is Nil');
  1157. Assert(p.ReferredType = context.GetType(TypeInfo(LongInt)), 'ReferredType of PLongInt is not a LongInt');
  1158. t := context.GetType(TypeInfo(PWideChar));
  1159. Assert(t is TRttiPointerType, 'Type of Pointer is not a TRttiPointerType');
  1160. Assert(Assigned(p.ReferredType), 'ReferredType of PWideChar is Nil');
  1161. Assert(p.ReferredType = context.GetType(TypeInfo(WideChar)), 'ReferredType of PWideChar is not a WideChar');
  1162. finally
  1163. context.Free;
  1164. end;
  1165. end;
  1166. procedure TTestCase1.GetClassProperties;
  1167. var
  1168. LContext: TRttiContext;
  1169. LType: TRttiType;
  1170. PropList, PropList2: {$ifdef fpc}specialize{$endif} TArray<TRttiProperty>;
  1171. i: LongInt;
  1172. begin
  1173. LContext := TRttiContext.Create;
  1174. LType := LContext.GetType(TypeInfo(TGetClassProperties));
  1175. PropList := LType.GetProperties;
  1176. CheckEquals(4, length(PropList));
  1177. CheckEquals('PubPropRO', PropList[0].Name);
  1178. CheckEquals('PubPropRW', PropList[1].Name);
  1179. CheckEquals('PubPropSetRO', PropList[2].Name);
  1180. CheckEquals('PubPropSetRW', PropList[3].Name);
  1181. LType := LContext.GetType(TypeInfo(TGetClassPropertiesSub));
  1182. PropList2 := LType.GetProperties;
  1183. CheckEquals(Length(PropList), Length(PropList2));
  1184. for i := 0 to High(PropList) do
  1185. Check(PropList[i] = PropList2[i], 'Property instances are not equal');
  1186. LContext.Free;
  1187. end;
  1188. procedure TTestCase1.GetClassPropertiesValue;
  1189. var
  1190. AGetClassProperties: TGetClassProperties;
  1191. LContext: TRttiContext;
  1192. LType: TRttiType;
  1193. AValue: TValue;
  1194. begin
  1195. LContext := TRttiContext.Create;
  1196. LType := LContext.GetType(TGetClassProperties);
  1197. AGetClassProperties := TGetClassProperties.Create;
  1198. try
  1199. AGetClassProperties.PubPropRW:=12345;
  1200. AValue := LType.GetProperty('PubPropRW').GetValue(AGetClassProperties);
  1201. CheckEquals(12345, AValue.AsInteger);
  1202. finally
  1203. AGetClassProperties.Free;
  1204. end;
  1205. LContext.Free;
  1206. end;
  1207. procedure TTestCase1.TestReferenceRawData;
  1208. var
  1209. value: TValue;
  1210. str: String;
  1211. intf: IInterface;
  1212. i: LongInt;
  1213. test: TTestRecord;
  1214. arrdyn: TArrayOfLongintDyn;
  1215. arrstat: TArrayOfLongintStatic;
  1216. begin
  1217. str := 'Hello World';
  1218. UniqueString(str);
  1219. TValue.Make(@str, TypeInfo(String), value);
  1220. Check(PPointer(value.GetReferenceToRawData)^ = Pointer(str), 'Reference to string data differs');
  1221. intf := TInterfacedObject.Create;
  1222. TValue.Make(@intf, TypeInfo(IInterface), value);
  1223. Check(PPointer(value.GetReferenceToRawData)^ = Pointer(intf), 'Reference to interface data differs');
  1224. i := 42;
  1225. TValue.Make(@i, TypeInfo(LongInt), value);
  1226. Check(value.GetReferenceToRawData <> @i, 'Reference to longint is equal');
  1227. Check(PLongInt(value.GetReferenceToRawData)^ = PLongInt(@i)^, 'Reference to longint data differs');
  1228. test.value1 := 42;
  1229. test.value2 := 'Hello World';
  1230. TValue.Make(@test, TypeInfo(TTestRecord), value);
  1231. Check(value.GetReferenceToRawData <> @test, 'Reference to record is equal');
  1232. Check(PTestRecord(value.GetReferenceToRawData)^.value1 = PTestRecord(@test)^.value1, 'Reference to record data value1 differs');
  1233. Check(PTestRecord(value.GetReferenceToRawData)^.value2 = PTestRecord(@test)^.value2, 'Reference to record data value2 differs');
  1234. SetLength(arrdyn, 3);
  1235. arrdyn[0] := 42;
  1236. arrdyn[1] := 23;
  1237. arrdyn[2] := 49;
  1238. TValue.Make(@arrdyn, TypeInfo(TArrayOfLongintDyn), value);
  1239. Check(PPointer(value.GetReferenceToRawData)^ = Pointer(arrdyn), 'Reference to dynamic array data differs');
  1240. arrstat[0] := 42;
  1241. arrstat[1] := 23;
  1242. arrstat[2] := 49;
  1243. arrstat[3] := 59;
  1244. TValue.Make(@arrstat, TypeInfo(TArrayOfLongintStatic), value);
  1245. Check(value.GetReferenceToRawData <> @arrstat, 'Reference to static array is equal');
  1246. Check(PLongInt(value.GetReferenceToRawData)^ = PLongInt(@arrstat)^, 'Reference to static array data differs');
  1247. end;
  1248. procedure TTestCase1.TestReferenceRawDataEmpty;
  1249. var
  1250. value: TValue;
  1251. begin
  1252. TValue.Make(Nil, TypeInfo(String), value);
  1253. Check(Assigned(value.GetReferenceToRawData()), 'Reference to empty String is not assigned');
  1254. Check(not Assigned(PPointer(value.GetReferenceToRawData)^), 'Empty String data is assigned');
  1255. TValue.Make(Nil, TypeInfo(IInterface), value);
  1256. Check(Assigned(value.GetReferenceToRawData()), 'Reference to empty interface is not assigned');
  1257. Check(not Assigned(PPointer(value.GetReferenceToRawData)^), 'Empty interface data is assigned');
  1258. TValue.Make(Nil, TypeInfo(LongInt), value);
  1259. Check(Assigned(value.GetReferenceToRawData()), 'Reference to empty LongInt is not assigned');
  1260. Check(PLongInt(value.GetReferenceToRawData)^ = 0, 'Empty longint data is not 0');
  1261. TValue.Make(Nil, TypeInfo(TTestRecord), value);
  1262. Check(Assigned(value.GetReferenceToRawData()), 'Reference to empty record is not assigned');
  1263. Check(PTestRecord(value.GetReferenceToRawData)^.value1 = 0, 'Empty record data value1 is not 0');
  1264. Check(PTestRecord(value.GetReferenceToRawData)^.value2 = '', 'Empty record data value2 is not empty');
  1265. TValue.Make(Nil, TypeInfo(TArrayOfLongintDyn), value);
  1266. Check(Assigned(value.GetReferenceToRawData()), 'Reference to empty dynamic array is not assigned');
  1267. Check(not Assigned(PPointer(value.GetReferenceToRawData)^), 'Empty dynamic array data is assigned');
  1268. TValue.Make(Nil, TypeInfo(TArrayOfLongintStatic), value);
  1269. Check(Assigned(value.GetReferenceToRawData()), 'Reference to empty static array is not assigned');
  1270. Check(PLongInt(value.GetReferenceToRawData)^ = 0, 'Empty static array data is not 0');
  1271. end;
  1272. procedure TTestCase1.TestDataSize;
  1273. var
  1274. u8: UInt8;
  1275. u16: UInt16;
  1276. u32: UInt32;
  1277. u64: UInt64;
  1278. s8: Int8;
  1279. s16: Int16;
  1280. s32: Int32;
  1281. s64: Int64;
  1282. f32: Single;
  1283. f64: Double;
  1284. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1285. f80: Extended;
  1286. {$endif}
  1287. fco: Comp;
  1288. fcu: Currency;
  1289. ss: ShortString;
  1290. sa: AnsiString;
  1291. su: UnicodeString;
  1292. sw: WideString;
  1293. o: TObject;
  1294. c: TClass;
  1295. i: IInterface;
  1296. ad: TArrayOfLongintDyn;
  1297. _as: TArrayOfLongintStatic;
  1298. b8: Boolean;
  1299. {$ifdef fpc}
  1300. b16: Boolean16;
  1301. b32: Boolean32;
  1302. b64: Boolean64;
  1303. {$endif}
  1304. bl8: ByteBool;
  1305. bl16: WordBool;
  1306. bl32: LongBool;
  1307. {$ifdef fpc}
  1308. bl64: QWordBool;
  1309. {$endif}
  1310. e: TTestEnum;
  1311. s: TTestSet;
  1312. t: TTestRecord;
  1313. p: Pointer;
  1314. proc: TTestProc;
  1315. method: TTestMethod;
  1316. value: TValue;
  1317. begin
  1318. u8:=245;
  1319. TValue.Make(@u8, TypeInfo(UInt8), value);
  1320. CheckEquals(1, value.DataSize, 'Size of UInt8 differs');
  1321. u16:=789;
  1322. TValue.Make(@u16, TypeInfo(UInt16), value);
  1323. CheckEquals(2, value.DataSize, 'Size of UInt16 differs');
  1324. u32:=568789;
  1325. TValue.Make(@u32, TypeInfo(UInt32), value);
  1326. CheckEquals(4, value.DataSize, 'Size of UInt32 differs');
  1327. u64:=$abdcefadbcef;
  1328. TValue.Make(@u64, TypeInfo(UInt64), value);
  1329. CheckEquals(8, value.DataSize, 'Size of UInt64 differs');
  1330. s8:=-32;
  1331. TValue.Make(@s8, TypeInfo(Int8), value);
  1332. CheckEquals(1, value.DataSize, 'Size of Int8 differs');
  1333. s16:=-5345;
  1334. TValue.Make(@s16, TypeInfo(Int16), value);
  1335. CheckEquals(2, value.DataSize, 'Size of Int16 differs');
  1336. s32:=-234567;
  1337. TValue.Make(@s32, TypeInfo(Int32), value);
  1338. CheckEquals(4, value.DataSize, 'Size of Int32 differs');
  1339. s64:=23456789012;
  1340. TValue.Make(@s64, TypeInfo(Int64), value);
  1341. CheckEquals(8, value.DataSize, 'Size of Int64 differs');
  1342. b8:=false;
  1343. TValue.Make(@b8, TypeInfo(Boolean), value);
  1344. CheckEquals(1, value.DataSize, 'Size of Boolean differs');
  1345. {$ifdef fpc}
  1346. b16:=true;
  1347. TValue.Make(@b16, TypeInfo(Boolean16), value);
  1348. CheckEquals(2, value.DataSize, 'Size of Boolean16 differs');
  1349. b32:=false;
  1350. TValue.Make(@b32, TypeInfo(Boolean32), value);
  1351. CheckEquals(4, value.DataSize, 'Size of Boolean32 differs');
  1352. b64:=true;
  1353. TValue.Make(@b64, TypeInfo(Boolean64), value);
  1354. CheckEquals(8, value.DataSize, 'Size of Boolean64 differs');
  1355. {$endif}
  1356. bl8:=true;
  1357. TValue.Make(@bl8, TypeInfo(ByteBool), value);
  1358. CheckEquals(1, value.DataSize, 'Size of ByteBool differs');
  1359. bl16:=false;
  1360. TValue.Make(@bl16, TypeInfo(WordBool), value);
  1361. CheckEquals(2, value.DataSize, 'Size of WordBool differs');
  1362. bl32:=false;
  1363. TValue.Make(@bl32, TypeInfo(LongBool), value);
  1364. CheckEquals(4, value.DataSize, 'Size of LongBool differs');
  1365. {$ifdef fpc}
  1366. bl64:=true;
  1367. TValue.Make(@bl64, TypeInfo(QWordBool), value);
  1368. CheckEquals(8, value.DataSize, 'Size of QWordBool differs');
  1369. {$endif}
  1370. f32:=4.567;
  1371. TValue.Make(@f32, TypeInfo(Single), value);
  1372. CheckEquals(4, value.DataSize, 'Size of Single differs');
  1373. f64:=-3456.678;
  1374. TValue.Make(@f64, TypeInfo(Double), value);
  1375. CheckEquals(8, value.DataSize, 'Size of Double differs');
  1376. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1377. f80:=-2345.678;
  1378. TValue.Make(@f80, TypeInfo(Extended), value);
  1379. CheckEquals(10, value.DataSize, 'Size of Extended differs');
  1380. {$endif}
  1381. fcu:=56.78;
  1382. TValue.Make(@fcu, TypeInfo(Currency), value);
  1383. CheckEquals(SizeOf(Currency), value.DataSize, 'Size of Currency differs');
  1384. fco:=456;
  1385. TValue.Make(@fco, TypeInfo(Comp), value);
  1386. CheckEquals(SizeOf(Comp), value.DataSize, 'Size of Comp differs');
  1387. ss := '';
  1388. TValue.Make(@ss, TypeInfo(ShortString), value);
  1389. CheckEquals(254, value.DataSize, 'Size ofShortString differs');
  1390. sa:= '';
  1391. TValue.Make(@sa, TypeInfo(AnsiString), value);
  1392. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of AnsiString differs');
  1393. sw := '';
  1394. TValue.Make(@sw, TypeInfo(WideString), value);
  1395. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of WideString differs');
  1396. su:='';
  1397. TValue.Make(@su, TypeInfo(UnicodeString), value);
  1398. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of UnicodeString differs');
  1399. o := TTestValueClass.Create;
  1400. TValue.Make(@o, TypeInfo(TObject), value);
  1401. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of TObject differs');
  1402. o.Free;
  1403. c := TObject;
  1404. TValue.Make(@c, TypeInfo(TClass), value);
  1405. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of TClass differs');
  1406. i := Nil;
  1407. TValue.Make(@i, TypeInfo(IInterface), value);
  1408. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of IInterface differs');
  1409. TValue.Make(@t, TypeInfo(TTestRecord), value);
  1410. CheckEquals(SizeOf(TTestRecord), value.DataSize, 'Size of TTestRecord differs');
  1411. proc := Nil;
  1412. TValue.Make(@proc, TypeInfo(TTestProc), value);
  1413. CheckEquals(SizeOf(TTestProc), value.DataSize, 'Size of TTestProc differs');
  1414. method := Nil;
  1415. TValue.Make(@method, TypeInfo(TTestMethod), value);
  1416. CheckEquals(SizeOf(TTestMethod), value.DataSize, 'Size of TTestMethod differs');
  1417. TValue.Make(@_as, TypeInfo(TArrayOfLongintStatic), value);
  1418. CheckEquals(SizeOf(TArrayOfLongintStatic), value.DataSize, 'Size of TArrayOfLongintStatic differs');
  1419. TValue.Make(@ad, TypeInfo(TArrayOfLongintDyn), value);
  1420. CheckEquals(SizeOf(TArrayOfLongintDyn), value.DataSize, 'Size of TArrayOfLongintDyn differs');
  1421. e:=low(TTestEnum);
  1422. TValue.Make(@e, TypeInfo(TTestEnum), value);
  1423. CheckEquals(SizeOf(TTestEnum), value.DataSize, 'Size of TTestEnum differs');
  1424. s:=[low(TTestEnum),high(TTestEnum)];
  1425. TValue.Make(@s, TypeInfo(TTestSet), value);
  1426. CheckEquals(SizeOf(TTestSet), value.DataSize, 'Size of TTestSet differs');
  1427. p := Nil;
  1428. TValue.Make(@p, TypeInfo(Pointer), value);
  1429. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of Pointer differs');
  1430. end;
  1431. procedure TTestCase1.TestDataSizeEmpty;
  1432. var
  1433. value: TValue;
  1434. begin
  1435. TValue.Make(Nil, TypeInfo(UInt8), value);
  1436. CheckEquals(1, value.DataSize, 'Size of UInt8 differs');
  1437. TValue.Make(Nil, TypeInfo(UInt16), value);
  1438. CheckEquals(2, value.DataSize, 'Size of UInt16 differs');
  1439. TValue.Make(Nil, TypeInfo(UInt32), value);
  1440. CheckEquals(4, value.DataSize, 'Size of UInt32 differs');
  1441. TValue.Make(Nil, TypeInfo(UInt64), value);
  1442. CheckEquals(8, value.DataSize, 'Size of UInt64 differs');
  1443. TValue.Make(Nil, TypeInfo(Int8), value);
  1444. CheckEquals(1, value.DataSize, 'Size of Int8 differs');
  1445. TValue.Make(Nil, TypeInfo(Int16), value);
  1446. CheckEquals(2, value.DataSize, 'Size of Int16 differs');
  1447. TValue.Make(Nil, TypeInfo(Int32), value);
  1448. CheckEquals(4, value.DataSize, 'Size of Int32 differs');
  1449. TValue.Make(Nil, TypeInfo(Int64), value);
  1450. CheckEquals(8, value.DataSize, 'Size of Int64 differs');
  1451. TValue.Make(Nil, TypeInfo(Boolean), value);
  1452. CheckEquals(1, value.DataSize, 'Size of Boolean differs');
  1453. {$ifdef fpc}
  1454. TValue.Make(Nil, TypeInfo(Boolean16), value);
  1455. CheckEquals(2, value.DataSize, 'Size of Boolean16 differs');
  1456. TValue.Make(Nil, TypeInfo(Boolean32), value);
  1457. CheckEquals(4, value.DataSize, 'Size of Boolean32 differs');
  1458. TValue.Make(Nil, TypeInfo(Boolean64), value);
  1459. CheckEquals(8, value.DataSize, 'Size of Boolean64 differs');
  1460. {$endif}
  1461. TValue.Make(Nil, TypeInfo(ByteBool), value);
  1462. CheckEquals(1, value.DataSize, 'Size of ByteBool differs');
  1463. TValue.Make(Nil, TypeInfo(WordBool), value);
  1464. CheckEquals(2, value.DataSize, 'Size of WordBool differs');
  1465. TValue.Make(Nil, TypeInfo(LongBool), value);
  1466. CheckEquals(4, value.DataSize, 'Size of LongBool differs');
  1467. {$ifdef fpc}
  1468. TValue.Make(Nil, TypeInfo(QWordBool), value);
  1469. CheckEquals(8, value.DataSize, 'Size of QWordBool differs');
  1470. {$endif}
  1471. TValue.Make(Nil, TypeInfo(Single), value);
  1472. CheckEquals(4, value.DataSize, 'Size of Single differs');
  1473. TValue.Make(Nil, TypeInfo(Double), value);
  1474. CheckEquals(8, value.DataSize, 'Size of Double differs');
  1475. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1476. TValue.Make(Nil, TypeInfo(Extended), value);
  1477. CheckEquals(10, value.DataSize, 'Size of Extended differs');
  1478. {$endif}
  1479. TValue.Make(Nil, TypeInfo(Currency), value);
  1480. CheckEquals(SizeOf(Currency), value.DataSize, 'Size of Currency differs');
  1481. TValue.Make(Nil, TypeInfo(Comp), value);
  1482. CheckEquals(SizeOf(Comp), value.DataSize, 'Size of Comp differs');
  1483. TValue.Make(Nil, TypeInfo(ShortString), value);
  1484. CheckEquals(254, value.DataSize, 'Size of ShortString differs');
  1485. TValue.Make(Nil, TypeInfo(AnsiString), value);
  1486. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of Pointer differs');
  1487. TValue.Make(Nil, TypeInfo(WideString), value);
  1488. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of WideString differs');
  1489. TValue.Make(Nil, TypeInfo(UnicodeString), value);
  1490. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of UnicodeString differs');
  1491. TValue.Make(Nil, TypeInfo(TObject), value);
  1492. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of TObject differs');
  1493. TValue.Make(Nil, TypeInfo(TClass), value);
  1494. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of TClass differs');
  1495. TValue.Make(Nil, TypeInfo(IInterface), value);
  1496. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of IInterface differs');
  1497. TValue.Make(Nil, TypeInfo(TTestRecord), value);
  1498. CheckEquals(SizeOf(TTestRecord), value.DataSize, 'Size of TTestRecord differs');
  1499. TValue.Make(Nil, TypeInfo(TTestProc), value);
  1500. CheckEquals(SizeOf(TTestProc), value.DataSize, 'Size of TTestProc differs');
  1501. TValue.Make(Nil, TypeInfo(TTestMethod), value);
  1502. CheckEquals(SizeOf(TTestMethod), value.DataSize, 'Size of TTestMethod differs');
  1503. TValue.Make(Nil, TypeInfo(TArrayOfLongintStatic), value);
  1504. CheckEquals(SizeOf(TArrayOfLongintStatic), value.DataSize, 'Size of TArrayOfLongintStatic differs');
  1505. TValue.Make(Nil, TypeInfo(TArrayOfLongintDyn), value);
  1506. CheckEquals(SizeOf(TArrayOfLongintDyn), value.DataSize, 'Size of TArrayOfLongintDyn differs');
  1507. TValue.Make(Nil, TypeInfo(TTestEnum), value);
  1508. CheckEquals(SizeOf(TTestEnum), value.DataSize, 'Size of TTestEnum differs');
  1509. TValue.Make(Nil, TypeInfo(TTestSet), value);
  1510. CheckEquals(SizeOf(TTestSet), value.DataSize, 'Size of TTestSet differs');
  1511. TValue.Make(Nil, TypeInfo(Pointer), value);
  1512. CheckEquals(SizeOf(Pointer), value.DataSize, 'Size of Pointer differs');
  1513. end;
  1514. procedure TTestCase1.TestIsManaged;
  1515. begin
  1516. CheckEquals(true, IsManaged(TypeInfo(ansistring)), 'IsManaged for tkAString');
  1517. CheckEquals(true, IsManaged(TypeInfo(widestring)), 'IsManaged for tkWString');
  1518. CheckEquals(true, IsManaged(TypeInfo(Variant)), 'IsManaged for tkVariant');
  1519. CheckEquals(true, IsManaged(TypeInfo(TArrayOfManagedRec)),
  1520. 'IsManaged for tkArray (with managed ElType)');
  1521. CheckEquals(true, IsManaged(TypeInfo(TArrayOfString)),
  1522. 'IsManaged for tkArray (with managed ElType)');
  1523. CheckEquals(true, IsManaged(TypeInfo(TManagedRec)), 'IsManaged for tkRecord');
  1524. {$ifdef fpc}
  1525. CheckEquals(true, IsManaged(TypeInfo(TManagedRecOp)), 'IsManaged for tkRecord');
  1526. {$endif}
  1527. CheckEquals(true, IsManaged(TypeInfo(IInterface)), 'IsManaged for tkInterface');
  1528. CheckEquals(true, IsManaged(TypeInfo(TManagedObj)), 'IsManaged for tkObject');
  1529. {$ifdef fpc}
  1530. CheckEquals(true, IsManaged(TypeInfo(specialize TArray<byte>)), 'IsManaged for tkDynArray');
  1531. {$else}
  1532. CheckEquals(true, IsManaged(TypeInfo(TArray<byte>)), 'IsManaged for tkDynArray');
  1533. {$endif}
  1534. CheckEquals(true, IsManaged(TypeInfo(unicodestring)), 'IsManaged for tkUString');
  1535. CheckEquals(false, IsManaged(TypeInfo(shortstring)), 'IsManaged for tkSString');
  1536. CheckEquals(false, IsManaged(TypeInfo(Byte)), 'IsManaged for tkInteger');
  1537. CheckEquals(false, IsManaged(TypeInfo(Char)), 'IsManaged for tkChar');
  1538. CheckEquals(false, IsManaged(TypeInfo(TTestEnum)), 'IsManaged for tkEnumeration');
  1539. CheckEquals(false, IsManaged(TypeInfo(Single)), 'IsManaged for tkFloat');
  1540. CheckEquals(false, IsManaged(TypeInfo(TTestSet)), 'IsManaged for tkSet');
  1541. {$ifdef fpc}
  1542. CheckEquals(false, IsManaged(TypeInfo(TTestMethod)), 'IsManaged for tkMethod');
  1543. {$else}
  1544. { Delphi bug (or sabotage). For some reason Delphi considers method pointers to be managed (only in newer versions, probably since XE7) :/ }
  1545. CheckEquals({$if RTLVersion>=28}true{$else}false{$endif}, IsManaged(TypeInfo(TTestMethod)), 'IsManaged for tkMethod');
  1546. {$endif}
  1547. CheckEquals(false, IsManaged(TypeInfo(TArrayOfByte)),
  1548. 'IsManaged for tkArray (with non managed ElType)');
  1549. CheckEquals(false, IsManaged(TypeInfo(TArrayOfNonManagedRec)),
  1550. 'IsManaged for tkArray (with non managed ElType)');
  1551. CheckEquals(false, IsManaged(TypeInfo(TNonManagedRec)), 'IsManaged for tkRecord');
  1552. CheckEquals(false, IsManaged(TypeInfo(TObject)), 'IsManaged for tkClass');
  1553. CheckEquals(false, IsManaged(TypeInfo(TNonManagedObj)), 'IsManaged for tkObject');
  1554. CheckEquals(false, IsManaged(TypeInfo(WideChar)), 'IsManaged for tkWChar');
  1555. CheckEquals(false, IsManaged(TypeInfo(Boolean)), 'IsManaged for tkBool');
  1556. CheckEquals(false, IsManaged(TypeInfo(Int64)), 'IsManaged for tkInt64');
  1557. CheckEquals(false, IsManaged(TypeInfo(UInt64)), 'IsManaged for tkQWord');
  1558. {$ifdef fpc}
  1559. CheckEquals(false, IsManaged(TypeInfo(ICORBATest)), 'IsManaged for tkInterfaceRaw');
  1560. {$endif}
  1561. CheckEquals(false, IsManaged(TypeInfo(TTestProc)), 'IsManaged for tkProcVar');
  1562. CheckEquals(false, IsManaged(TypeInfo(TTestHelper)), 'IsManaged for tkHelper');
  1563. {$ifdef fpc}
  1564. CheckEquals(false, IsManaged(TypeInfo(file)), 'IsManaged for tkFile');
  1565. {$endif}
  1566. CheckEquals(false, IsManaged(TypeInfo(TClass)), 'IsManaged for tkClassRef');
  1567. CheckEquals(false, IsManaged(TypeInfo(Pointer)), 'IsManaged for tkPointer');
  1568. CheckEquals(false, IsManaged(nil), 'IsManaged for nil');
  1569. end;
  1570. {$ifdef fpc}
  1571. procedure TTestCase1.TestOpenArrayToDyn;
  1572. procedure OpenArrayProc(aArr: array of LongInt);
  1573. var
  1574. value: TValue;
  1575. begin
  1576. {$ifndef InLazIDE}
  1577. value := specialize OpenArrayToDynArrayValue<LongInt>(aArr);
  1578. {$endif}
  1579. CheckEquals(value.IsArray, True);
  1580. CheckEquals(value.IsOpenArray, False);
  1581. CheckEquals(value.IsObject, False);
  1582. CheckEquals(value.IsOrdinal, False);
  1583. CheckEquals(value.IsClass, False);
  1584. CheckEquals(value.GetArrayLength, 2);
  1585. CheckEquals(value.GetArrayElement(0).AsInteger, 42);
  1586. CheckEquals(value.GetArrayElement(1).AsInteger, 84);
  1587. value.SetArrayElement(0, 21);
  1588. { since this is a copy the original array is not modified! }
  1589. CheckEquals(aArr[0], 42);
  1590. end;
  1591. begin
  1592. OpenArrayProc([42, 84]);
  1593. end;
  1594. {$endif}
  1595. procedure TTestCase1.TestInterface;
  1596. var
  1597. context: TRttiContext;
  1598. t: TRttiType;
  1599. ti1, ti2: TRttiInterfaceType;
  1600. methods: {$ifdef fpc}specialize{$endif} TArray<TRttiMethod>;
  1601. params: {$ifdef fpc}specialize{$endif} TArray<TRttiParameter>;
  1602. method: TRttiMethod;
  1603. param: TRttiParameter;
  1604. flag: TParamFlag;
  1605. begin
  1606. context := TRttiContext.Create;
  1607. try
  1608. t := context.GetType(TypeInfo(IInterface));
  1609. Check(t is TRttiInterfaceType, 'Type is not an interface type');
  1610. Check(not Assigned(t.BaseType), 'Base type is assigned');
  1611. ti1 := TRttiInterfaceType(t);
  1612. Check(not Assigned(ti1.BaseType), 'Base type is assigned');
  1613. methods := t.GetMethods;
  1614. CheckEquals(0, Length(methods), 'Overall method count does not match');
  1615. methods := t.GetDeclaredMethods;
  1616. CheckEquals(0, Length(methods), 'Declared method conut does not match');
  1617. t := context.GetType(TypeInfo(ITestInterface));
  1618. Check(t is TRttiInterfaceType, 'Type is not an interface type');
  1619. Check(Assigned(t.BaseType), 'Base type is not assigned');
  1620. Check(t.BaseType = TRttiType(ti1), 'Base type does not match');
  1621. ti2 := TRttiInterfaceType(t);
  1622. Check(Assigned(ti2.BaseType), 'Base type is not assigned');
  1623. Check(ti2.BaseType = ti1, 'Base type does not match');
  1624. methods := t.GetMethods;
  1625. CheckEquals(4, Length(methods), 'Overall method count does not match');
  1626. methods := t.GetDeclaredMethods;
  1627. CheckEquals(4, Length(methods), 'Declared method count does not match');
  1628. method := methods[0];
  1629. CheckEquals(method.Name, 'Test', 'Method name of Test does not match');
  1630. Check(method.CallingConvention = DefaultCC, 'Calling convention of Test does not match');
  1631. Check(method.MethodKind = mkProcedure, 'Method kind of Test does not match');
  1632. Check(method.DispatchKind = dkInterface, 'Dispatch kind of Test does not match');
  1633. Check(not Assigned(method.CodeAddress), 'Code address of Test is not Nil');
  1634. CheckEquals(method.VirtualIndex, 3, 'Virtual index of Test does not match');
  1635. Check(not Assigned(method.ReturnType), 'Return type of Test is not Nil');
  1636. params := method.GetParameters;
  1637. CheckEquals(0, Length(params), 'Parameter count of Test does not match');
  1638. method := methods[1];
  1639. CheckEquals(method.Name, 'Test2', 'Method name of Test2 does not match');
  1640. Check(method.CallingConvention = DefaultCC, 'Calling convention of Test2 does not match');
  1641. Check(method.MethodKind = mkFunction, 'Method kind of Test2 does not match');
  1642. Check(method.DispatchKind = dkInterface, 'Dispatch kind of Test2 does not match');
  1643. Check(not Assigned(method.CodeAddress), 'Code address of Test2 is not Nil');
  1644. CheckEquals(method.VirtualIndex, 4, 'Virtual index of Test2 does not match');
  1645. Check(Assigned(method.ReturnType), 'Return type of Test2 is Nil');
  1646. Check(method.ReturnType.TypeKind = tkInteger, 'Return type of Test2 is not an ordinal');
  1647. params := method.GetParameters;
  1648. CheckEquals(0, Length(params), 'Parameter count of Test2 does not match');
  1649. method := methods[2];
  1650. CheckEquals(method.Name, 'Test3', 'Method name of Test3 does not match');
  1651. Check(method.CallingConvention = DefaultCC, 'Calling convention of Test3 does not match');
  1652. Check(method.MethodKind = mkProcedure, 'Method kind of Test3 does not match');
  1653. Check(method.DispatchKind = dkInterface, 'Dispatch kind of Test3 does not match');
  1654. Check(not Assigned(method.CodeAddress), 'Code address of Test3 is not Nil');
  1655. CheckEquals(method.VirtualIndex, 5, 'Virtual index of Test3 does not match');
  1656. Check(not Assigned(method.ReturnType), 'Return type of Test3 is not Nil');
  1657. params := method.GetParameters;
  1658. CheckEquals(4, Length(params), 'Parameter count of Test3 does not match');
  1659. param := params[0];
  1660. CheckEquals(param.Name, 'aArg1', 'Parameter name of Test3.aArg1 does not match');
  1661. Check(param.Flags = [], 'Parameter flags of Test3.aArg1 do not match');
  1662. Check(Assigned(param.ParamType), 'Parameter type of Test3.aArg1 is Nil');
  1663. Check(param.ParamType.TypeKind = tkInteger, 'Parameter type of Test3.aArg1 is not an ordinal');
  1664. param := params[1];
  1665. CheckEquals(param.Name, 'aArg2', 'Parameter name of Test3.aArg2 does not match');
  1666. Check(param.Flags = [pfConst], 'Parameter flags of Test3.aArg2 do not match');
  1667. Check(Assigned(param.ParamType), 'Parameter type of Test3.aArg2 is Nil');
  1668. Check(param.ParamType.TypeKind = tkAnsiString, 'Parameter type of Test3.aArg2 is not a string');
  1669. param := params[2];
  1670. CheckEquals(param.Name, 'aArg3', 'Parameter name of Test3.aArg3 does not match');
  1671. Check(param.Flags = [pfVar], 'Parameter flags of Test3.aArg3 do not match');
  1672. Check(Assigned(param.ParamType), 'Parameter type of Test3.aArg3 is Nil');
  1673. Check(param.ParamType.TypeKind = {$ifdef fpc}tkBool{$else}tkEnumeration{$endif}, 'Parameter type of Test3.aArg3 is not a boolean');
  1674. param := params[3];
  1675. CheckEquals(param.Name, 'aArg4', 'Parameter name of Test3.aArg4 does not match');
  1676. Check(param.Flags = [pfOut], 'Parameter flags of Test3.aArg4 do not match');
  1677. Check(Assigned(param.ParamType), 'Parameter type of Test3.aArg4 is Nil');
  1678. Check(param.ParamType.TypeKind = tkInteger, 'Parameter type of Test3.aArg4 is not a string');
  1679. method := methods[3];
  1680. CheckEquals(method.Name, 'Test4', 'Method name of Test4 does not match');
  1681. Check(method.CallingConvention = DefaultCC, 'Calling convention of Test4 does not match');
  1682. Check(method.MethodKind = mkFunction, 'Method kind of Test4 does not match');
  1683. Check(method.DispatchKind = dkInterface, 'Dispatch kind of Test4 does not match');
  1684. Check(not Assigned(method.CodeAddress), 'Code address of Test4 is not Nil');
  1685. CheckEquals(method.VirtualIndex, 6, 'Virtual index of Test4 does not match');
  1686. Check(Assigned(method.ReturnType), 'Return type of Test4 is not Nil');
  1687. Check(method.ReturnType.TypeKind = tkAnsiString, 'Return type of Test4 is not a string');
  1688. params := method.GetParameters;
  1689. CheckEquals(2, Length(params), 'Parameter count of Test4 does not match');
  1690. param := params[0];
  1691. CheckEquals(param.Name, 'aArg1', 'Parameter name of Test4.aArg1 does not match');
  1692. Check(param.Flags = [pfArray, pfReference], 'Parameter flags of Test4.aArg1 do not match');
  1693. Check(Assigned(param.ParamType), 'Parameter type of Test4.aArg1 is Nil');
  1694. Check(param.ParamType.TypeKind = tkInteger, 'Parameter type of Test4.aArg1 is not an ordinal');
  1695. param := params[1];
  1696. CheckEquals(param.Name, 'aArg2', 'Parameter name of Test4.aArg2 does not match');
  1697. Check(param.Flags = [pfArray, pfReference], 'Parameter flags of Test4.aArg2 do not match');
  1698. Check(Assigned(param.ParamType), 'Parameter type of Test4.aArg2 is Nil');
  1699. Check(param.ParamType.TypeKind = tkRecord, 'Parameter type of Test4.aArg2 is not a record');
  1700. finally
  1701. context.Free;
  1702. end;
  1703. end;
  1704. procedure TTestCase1.TestRawThunk;
  1705. var
  1706. intf: IInterface;
  1707. begin
  1708. { we test the raw thunking by instantiating a TVirtualInterface of IInterface }
  1709. { this does not require a function call manager as the thunking is implemented
  1710. directly inside the RTTI unit }
  1711. try
  1712. intf := TVirtualInterface.Create(PTypeInfo(TypeInfo(IInterface))) as IInterface;
  1713. except
  1714. on e: ENotImplemented do
  1715. Ignore('RawThunk not implemented');
  1716. end;
  1717. { if all went well QueryInterface and _AddRef were called and now we call
  1718. _Release as well }
  1719. intf := Nil;
  1720. end;
  1721. {$ifdef fpc}
  1722. procedure TTestCase1.TestInterfaceRaw;
  1723. var
  1724. context: TRttiContext;
  1725. t: TRttiType;
  1726. ti: TRttiInterfaceType;
  1727. begin
  1728. context := TRttiContext.Create;
  1729. try
  1730. t := context.GetType(TypeInfo(ICORBATest));
  1731. Check(t is TRttiInterfaceType, 'Type is not a raw interface type');
  1732. Check(not Assigned(t.BaseType), 'Base type is assigned');
  1733. ti := TRttiInterfaceType(t);
  1734. Check(not Assigned(ti.BaseType), 'Base type is assigned');
  1735. finally
  1736. context.Free;
  1737. end;
  1738. end;
  1739. {$endif}
  1740. procedure TTestCase1.TestProcVar;
  1741. var
  1742. context: TRttiContext;
  1743. t: TRttiType;
  1744. p: TRttiProcedureType;
  1745. params: {$ifdef fpc}specialize{$endif} TArray<TRttiParameter>;
  1746. begin
  1747. context := TRttiContext.Create;
  1748. try
  1749. t := context.GetType(PTypeInfo(TypeInfo(TTestProc)));
  1750. Check(Assigned(t), 'Rtti Type is Nil');
  1751. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1752. Check(t is TRttiProcedureType, 'Rtti Type is not a procedure type');
  1753. p := t as TRttiProcedureType;
  1754. Check(p.CallingConvention = DefaultCC, 'Calling convention does not match');
  1755. Check(not Assigned(p.ReturnType), 'Return type is assigned');
  1756. CheckEquals(0, Length(p.GetParameters), 'Procedure variable has parameters');
  1757. t := context.GetType(PTypeInfo(TypeInfo(TTestFunc1)));
  1758. Check(Assigned(t), 'Rtti Type is Nil');
  1759. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1760. Check(t is TRttiProcedureType, 'Rtti Type is not a procedure type');
  1761. p := t as TRttiProcedureType;
  1762. Check(p.CallingConvention = DefaultCC, 'Calling convention does not match');
  1763. Check(Assigned(p.ReturnType), 'Return type is not assigned');
  1764. //Check(p.ReturnType is TRttiOrdinalType, 'Return type is not an ordinal type');
  1765. CheckEquals(0, Length(p.GetParameters), 'Procedure variable has parameters');
  1766. t := context.GetType(PTypeInfo(TypeInfo(TTestFunc2)));
  1767. Check(Assigned(t), 'Rtti Type is Nil');
  1768. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1769. Check(t is TRttiProcedureType, 'Rtti Type is not a procedure type');
  1770. p := t as TRttiProcedureType;
  1771. Check(p.CallingConvention = DefaultCC, 'Calling convention does not match');
  1772. Check(Assigned(p.ReturnType), 'Return type is not assigned');
  1773. Check(p.ReturnType is TRttiStringType, 'Return type is not a string type');
  1774. params := p.GetParameters;
  1775. CheckEquals(2, Length(params), 'Procedure variable has incorrect amount of parameters');
  1776. Check(params[0].ParamType.TypeKind in [tkInteger, tkInt64], 'Parameter 1 is not an ordinal type');
  1777. //Check(params[0].ParamType is TRttiOrdinalType, 'Parameter 1 is not an ordinal type');
  1778. Check(pfArray in params[1].Flags, 'Parameter 2 is not an array');
  1779. Check(params[1].ParamType.TypeKind in [tkInteger, tkInt64], 'Parameter 2 is not an ordinal array');
  1780. finally
  1781. context.Free;
  1782. end;
  1783. end;
  1784. procedure TTestCase1.TestMethod;
  1785. var
  1786. context: TRttiContext;
  1787. t: TRttiType;
  1788. m: TRttiMethodType;
  1789. params: {$ifdef fpc}specialize{$endif} TArray<TRttiParameter>;
  1790. begin
  1791. context := TRttiContext.Create;
  1792. try
  1793. t := context.GetType(PTypeInfo(TypeInfo(TTestMethod)));
  1794. Check(Assigned(t), 'Rtti Type is Nil');
  1795. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1796. Check(t is TRttiMethodType, 'Rtti Type is not a method type');
  1797. m := t as TRttiMethodType;
  1798. Check(m.CallingConvention = DefaultCC, 'Calling convention does not match');
  1799. Check(not Assigned(m.ReturnType), 'Return type is assigned');
  1800. CheckEquals(0, Length(m.GetParameters), 'Method variable has parameters');
  1801. t := context.GetType(PTypeInfo(TypeInfo(TTestMethod1)));
  1802. Check(Assigned(t), 'Rtti Type is Nil');
  1803. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1804. Check(t is TRttiMethodType, 'Rtti Type is not a method type');
  1805. m := t as TRttiMethodType;
  1806. Check(m.CallingConvention = DefaultCC, 'Calling convention does not match');
  1807. Check(Assigned(m.ReturnType), 'Return type is not assigned');
  1808. //Check(p.ReturnType is TRttiOrdinalType, 'Return type is not an ordinal type');
  1809. CheckEquals(0, Length(m.GetParameters), 'Method variable has parameters');
  1810. t := context.GetType(PTypeInfo(TypeInfo(TTestMethod2)));
  1811. Check(Assigned(t), 'Rtti Type is Nil');
  1812. Check(t is TRttiInvokableType, 'Rtti Type is not an invokeable');
  1813. Check(t is TRttiMethodType, 'Rtti Type is not a method type');
  1814. m := t as TRttiMethodType;
  1815. Check(m.CallingConvention = DefaultCC, 'Calling convention does not match');
  1816. Check(Assigned(m.ReturnType), 'Return type is not assigned');
  1817. Check(m.ReturnType is TRttiStringType, 'Return type is not a string type');
  1818. params := m.GetParameters;
  1819. CheckEquals(2, Length(params), 'Method variable has incorrect amount of parameters');
  1820. Check(params[0].ParamType.TypeKind in [tkInteger, tkInt64], 'Parameter 1 is not an ordinal type');
  1821. //Check(params[0].ParamType is TRttiOrdinalType, 'Parameter 1 is not an ordinal type');
  1822. Check(pfArray in params[1].Flags, 'Parameter 2 is not an array');
  1823. Check(params[1].ParamType.TypeKind in [tkInteger, tkInt64], 'Parameter 2 is not an ordinal array');
  1824. finally
  1825. context.Free;
  1826. end;
  1827. end;
  1828. initialization
  1829. {$ifdef fpc}
  1830. RegisterTest(TTestCase1);
  1831. {$else fpc}
  1832. RegisterTest(TTestCase1.Suite);
  1833. {$endif fpc}
  1834. end.