utcwitparser.pp 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900
  1. {
  2. This file is part of the Free Component Library (FCL)
  3. Copyright (c) 2025 Michael Van Canneyt ([email protected])
  4. Test WIT parser
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit utcwitparser;
  12. interface
  13. // uncomment this to show parsed WIT content }
  14. { $DEFINE LOGPARSEDCONTENT}
  15. uses
  16. fpcunit, testregistry, Classes, SysUtils,
  17. WIT.Scanner, WIT.Model, WIT.Parser;
  18. type
  19. TResultIgnore = (riResult,riError);
  20. TResultIgnores = set of TResultIgnore;
  21. { TTestWITParser }
  22. TTestWITParser = class(TTestCase)
  23. private
  24. FScanner: TWITScanner;
  25. FParser: TWITParser;
  26. FDocument: TWITDocument;
  27. FInputStream: TStringStream;
  28. protected
  29. procedure SetUp; override;
  30. procedure TearDown; override;
  31. procedure InitParser(const aContent: string);
  32. class function AssertListType(const aMsg: string; aTypeDef: TWitTypeDef;const aName: String; aElementKind: TWITTypeKind; aCount : Integer = 0): TWitType;
  33. class function AssertEnumType(const aMsg: String; aType: TWITTypeDef;const aName: String; aValues: array of string) : TWITEnumType;
  34. class function AssertResultType(const aMsg: string; aType: TWITTypeDef;const aName: String; aOKKind: TWITTypeKind; aErrorKind: TWitTypeKind; aIgnore: TResultIgnores) : TWITResultType;
  35. class function AssertOptionType(const aMsg: string; aType: TWITTypeDef;const aName: String; aOptionKind: TWITTypeKind) : TWITOptionType;
  36. class function AssertStreamType(const aMsg: string; aType: TWITTypeDef;const aName: String; aStreamKind: TWITTypeKind): TWITStreamType;
  37. class function AssertFutureType(const aMsg: string; aType: TWITTypeDef;const aName: String; aFutureKind: TWITTypeKind): TWITFutureType;
  38. class function AssertTupleType(const aMsg: string; aType: TWITTypeDef;const aName: String; aOptionKind: Array of TWITTypeKind) : TWITTupleType;
  39. class function AssertFlagsType(const aMsg: string; aType: TWITTypeDef;const aName: String; aFlagNames: Array of String) : TWITFlagsType;
  40. class function AssertVariantType(const aMsg: string; aType: TWITTypeDef;const aName: String; aVariantNames: array of String): TWITVariantType;
  41. class function AssertRecordType(const aMsg: string; aType: TWITTypeDef;const aName: String; aFieldNames: array of String; aFieldTypes : Array of TWITTypeKind): TWITRecordType;
  42. class function AssertResourceType(const aMsg: string; aType: TWITTypeDef;const aName: String; aConstructor: boolean; aFunctionNames: array of String): TWITResourceType;
  43. class function AssertAliasType(const aMsg: string; aType: TWITTypeDef;const aName: String; aAliasName:String): TWITIdentifierType;
  44. class function AssertHandleType(const aMsg: string; aType: TWITTypeDef;const aName: String; aAliasName:String): TWITHandleType;
  45. class function AssertTypeDef(const Msg: String; aType: TWITType; aExpectedName: string; aExpectedUnderlyingKind: TWITTypeKind) : TWITType;
  46. class procedure AssertAnnotationArgument(const Msg: String; aArgument: TWITAnnotationArgument; aName, aValue: string);
  47. class procedure AssertAnnotation(const Msg: String; aAnnotation: TWITAnnotation;const aName: String; Args: array of String);
  48. class procedure AssertInclude(const aMsg: string; aInclude: TWITInclude;const aName: String; aItemNames, aItemAliases: array of String);
  49. class procedure AssertFunction(const Msg: String; aFunc: TWITFunction;const aName: String; aArgCount: Integer; aHaveResult: Boolean; aAnnotationCount: Integer = 0);
  50. class procedure AssertFunctionParam(const Msg: String; aParam: TWITFuncParam;const aName: String; aTypeKind: TWITTypeKind; aTypeName: string);
  51. class procedure AssertInterface(const Msg: String; aIntf: TWITInterface;const aName: String; aFuncCount: Integer; aTypeCount : Integer; aAnnotationCount: Integer = 0);
  52. class procedure AssertWorld(const Msg : String; aWorld :TWITWorld; const aWorldName : String; aExportCount,aImportCount,aUseCount,aTypeDefCount,aIncludeCount : Integer);
  53. class procedure AssertEquals(Msg: string; aExpected, aActual: TWitTypeKind); overload;
  54. class procedure AssertUse(Msg: string; aUse : TWITTopLevelUse; const aPackageName, aVersion, aIdentifier, aRename: string; aNameSpaces : Array of string);
  55. class procedure AssertUsePath(Msg: string; aUse: TWITUsePath; const aPackageName, aVersion, aIdentifier: string; aNameSpaces: array of string);
  56. class procedure AssertPackage(const Msg: String; aPackage: TWITPackage; aExpectedNamespace: string; aExpectedPackageName: string;
  57. aExpectedVersion: string; aExpectedWorldCount: Integer=0; aExpectedImportCount: Integer=0; aExpectedExportCount: Integer=0;
  58. aExpectedUseCount: Integer=0; aExpectedInterfaceCount: Integer=0);
  59. Protected
  60. function ParseWorld(const aWorldName : String; aExportCount,aImportCount,aUseCount,aTypeDefCount,aIncludeCount : Integer) : TWITWorld;
  61. function ParseFunc(const aFuncName: String; aArgNames : Array of string; aArgTypes : Array of TWitTypeKind; aResultType : TWitTypeKind = wtVoid): TWITFunction;
  62. function ParseType(const aInterFaceName, aTypeName: String): TWITTypeDef;
  63. function ParseInterface(const aName: String; aFunctionCount, aTypeCount, aAnnotationCount: integer): TWITInterface;
  64. function WrapTypeDef(const aDef: String; isType : Boolean = false): string;
  65. function WrapFunc(const aParams: String; aResult : string = ''): string;
  66. published
  67. procedure TestParsePackageEmpty;
  68. procedure TestParseExitInterfaceDocument;
  69. procedure TestParsePackageVersions;
  70. procedure TestSimpleTypes;
  71. procedure TestListType;
  72. procedure TestListListType;
  73. procedure TestListSized;
  74. procedure TestListSizedListSized;
  75. procedure TestEnum;
  76. procedure TestEnumEndWithComma;
  77. procedure TestResultEmpty;
  78. procedure TestResultOneType;
  79. procedure TestResultTwoTypes;
  80. procedure TestResultOneIgnoredTyoe;
  81. procedure TestOption;
  82. procedure TestStream;
  83. procedure TestStreamEmpty;
  84. procedure TestFuture;
  85. procedure TestNestedFuture;
  86. procedure TestFutureEmpty;
  87. procedure TestTupleEmpty;
  88. procedure TestTuple1;
  89. procedure TestTuple2;
  90. procedure TestTuple3;
  91. procedure TestTupleComma;
  92. procedure TestFlagsEmpty;
  93. procedure TestFlags1;
  94. procedure TestFlags2;
  95. procedure TestFlags3;
  96. procedure TestFlagsComma;
  97. procedure TestVariant1;
  98. procedure TestVariant2;
  99. procedure TestVariant2Comma;
  100. procedure TestVariantTypedSimple;
  101. procedure TestVariantTypedSimpleComma;
  102. procedure TestVariantTypedComplex;
  103. procedure TestRecordEmpty;
  104. procedure TestRecord1;
  105. procedure TestRecord2;
  106. procedure TestRecord2Comma;
  107. procedure TestRecordRecordName;
  108. procedure TestAlias;
  109. procedure TestBorrowedHandle;
  110. procedure TestResourceEmpty;
  111. procedure TestResourceEmpty2;
  112. procedure TestResourceConstructor;
  113. procedure TestResourceOneMethod;
  114. procedure TestResourceStaticMethod;
  115. procedure TestResourceAsyncMethod;
  116. procedure TestResourceTwoMethods;
  117. procedure TestResourceOneMethodAndConstructor;
  118. procedure TestUseIdentifier;
  119. procedure TestUseIdentifierAs;
  120. procedure TestUseFullIdentifier;
  121. procedure TestUseFullIdentifierVersion;
  122. procedure TestUseFullIdentifierAs;
  123. procedure TestUseFullIdentifierVersionAs;
  124. procedure TestParseFunctionEmpty;
  125. procedure TestParseFunctionEmptyResult;
  126. procedure TestParseFunctionOneParam;
  127. procedure TestParseFunctionOneParamResult;
  128. procedure TestParseFunctionTwoParams;
  129. procedure TestParseFunctionTwoParamsResult;
  130. procedure TestParseWorldEmpty;
  131. procedure TestParseWorldUse;
  132. procedure TestParseWorldUseAnnotation;
  133. procedure TestParseWorldExport;
  134. procedure TestParseWorldExportUse;
  135. procedure TestParseWorldExportFunction;
  136. procedure TestParseWorldExportInterface;
  137. procedure TestParseWorldImport;
  138. procedure TestParseWorldImportUse;
  139. procedure TestParseWorldImportFunction;
  140. procedure TestParseWorldImportInterface;
  141. procedure TestParseWorldInclude;
  142. procedure TestParseWorldIncludeUse;
  143. procedure TestParseWorldIncludeUseList;
  144. procedure TestParseWorldIncludeUseList2;
  145. procedure TestParseWorldTypeDef;
  146. procedure TestParseWorldEnumType;
  147. procedure TestParseWorldVariantType;
  148. procedure TestParseWorldRecordType;
  149. procedure TestParseWorldFlagsType;
  150. procedure TestParseInterfaceUse;
  151. procedure TestParseInterfaceUseGate;
  152. end;
  153. implementation
  154. uses TypInfo;
  155. { TTestWITParser }
  156. procedure TTestWITParser.InitParser(const aContent : string);
  157. begin
  158. FreeAndNil(FDocument);
  159. FreeAndNil(FInputStream);
  160. {$IFDEF LOGPARSEDCONTENT}
  161. Writeln(TestName,' - Parsing:');
  162. Writeln(aContent);
  163. {$ENDIF}
  164. FInputStream := TStringStream.Create(aContent);
  165. // Assuming TWITScanner.Create(AStream: TStream);
  166. // If TWITScanner has a different constructor (e.g., taking ownership of stream), adjust accordingly.
  167. FreeAndNil(FScanner);
  168. FScanner := TWITScanner.Create(FInputStream);
  169. FreeAndNil(FParser);
  170. FParser := TWITParser.Create(FScanner);
  171. end;
  172. procedure TTestWITParser.SetUp;
  173. begin
  174. inherited SetUp;
  175. FreeAndNil(FDocument); // Freeing nil is safe
  176. FreeAndNil(FParser);
  177. FreeAndNil(FScanner); // Assuming scanner does not own the stream, or handles it.
  178. FreeAndNil(FInputStream);
  179. end;
  180. procedure TTestWITParser.TearDown;
  181. begin
  182. FreeAndNil(FDocument); // Freeing nil is safe
  183. FreeAndNil(FParser);
  184. FreeAndNil(FScanner); // Assuming scanner does not own the stream, or handles it.
  185. FreeAndNil(FInputStream);
  186. inherited TearDown;
  187. end;
  188. function TTestWITParser.WrapTypeDef(const aDef: String; isType: Boolean): string;
  189. const
  190. WIT_CONTENT =
  191. 'interface types {' + sLineBreak +
  192. ' %s' + sLineBreak +
  193. '}';
  194. begin
  195. Result:=aDef;
  196. if isType then
  197. Result:='type a = '+Result+';';
  198. Result:=Format(WIT_CONTENT,[Result]);
  199. end;
  200. function TTestWITParser.WrapFunc(const aParams: String; aResult: string): string;
  201. const
  202. WIT_CONTENT =
  203. 'interface funcs {' + sLineBreak +
  204. ' %s' + sLineBreak +
  205. '}';
  206. var
  207. lWIT : String;
  208. begin
  209. lWIT:='a : func ('+aParams+')';
  210. if (aResult<>'') then
  211. lWIT:=lWIT+' -> '+aResult;
  212. lWIT:=lWIT+';';
  213. Result:=Format(WIT_CONTENT,[lWIT]);
  214. end;
  215. class procedure TTestWITParser.AssertEquals(Msg: string; aExpected, aActual: TWitTypeKind);
  216. begin
  217. AssertEquals(Msg,GetEnumName(TypeInfo(TWitTypeKind),ord(aExpected)),
  218. GetEnumName(TypeInfo(TWitTypeKind),ord(aActual)));
  219. end;
  220. class procedure TTestWITParser.AssertUsePath(Msg: string; aUse: TWITUsePath; const aPackageName, aVersion, aIdentifier: string;
  221. aNameSpaces: array of string);
  222. var
  223. I : Integer;
  224. begin
  225. AssertEquals(Msg+': PackageName',aPackageName,aUse.PackageName);
  226. AssertEquals(Msg+': Version',aVersion,aUse.Version);
  227. AssertEquals(Msg+': Identifier',aIdentifier,aUse.Identifier);
  228. AssertEquals(Msg+': Namespace count',Length(aNameSpaces),aUse.Namespaces.Count);
  229. For I:=0 to Length(aNamespaces)-1 do
  230. AssertEquals(Msg+Format(': namespace[%d]',[i]),aNameSpaces[i],aUse.Namespaces[i]);
  231. end;
  232. class procedure TTestWITParser.AssertUse(Msg: string; aUse: TWITTopLevelUse; const aPackageName, aVersion, aIdentifier, aRename: string;
  233. aNameSpaces: array of string);
  234. begin
  235. AssertNotNull(Msg+': Have use',aUse);
  236. AssertUsePath(Msg+': Path',aUse.Path,aPackageName,aVersion,aIdentifier,aNameSpaces);
  237. AssertEquals(Msg+': Rename',aRename,aUse.Rename);
  238. end;
  239. class procedure TTestWITParser.AssertAnnotationArgument(const Msg : String; aArgument : TWITAnnotationArgument; aName,aValue : string);
  240. begin
  241. AssertNotNull(Msg+': Have argument',aArgument);
  242. AssertEquals(Msg+': name',aName,aArgument.Member);
  243. AssertEquals(Msg+': value',aValue,aArgument.Value);
  244. end;
  245. class procedure TTestWITParser.AssertAnnotation(const Msg: String; aAnnotation: TWITAnnotation;const aName: String;
  246. Args: array of String);
  247. var
  248. I : Integer;
  249. begin
  250. AssertNotNull(Msg+': Have annotation',aAnnotation);
  251. AssertEquals(Msg+': name',aName,aAnnotation.Name);
  252. AssertEquals(Msg+': Arg count',aAnnotation.Arguments.Count,Length(Args) div 2);
  253. I:=0;
  254. While (I<Length(Args)) do
  255. begin
  256. AssertAnnotationArgument(Msg+Format('Annotation[%d]',[i]),aAnnotation.Arguments[I div 2],Args[i],Args[i+1]);
  257. Inc(I,2);
  258. end;
  259. end;
  260. class procedure TTestWITParser.AssertInclude(const aMsg: string; aInclude: TWITInclude; const aName: String; aItemNames,
  261. aItemAliases: array of String);
  262. begin
  263. AssertNotNull(aMsg+': have include',aInclude);
  264. AssertNotNull(aMsg+': have include path',aInclude.Path);
  265. AssertNotNull(aMsg+': items',aInclude.Items);
  266. AssertEquals(aMsg+': have path',aName,aInclude.Path.ToString);
  267. AssertEquals(aMsg+': item count',Length(aItemNames),aInclude.Items.Count);
  268. end;
  269. class procedure TTestWITParser.AssertFunction(const Msg: String; aFunc: TWITFunction; const aName: String; aArgCount: Integer;
  270. aHaveResult: Boolean; aAnnotationCount: Integer);
  271. begin
  272. AssertNotNull(Msg+': Have function',aFunc);
  273. AssertEquals(Msg+': name',aName,aFunc.Name);
  274. AssertNotNull(Msg+': Type',aFunc.TypeDef);
  275. AssertEquals(Msg+': Argument count',aArgCount,aFunc.TypeDef.Parameters.Count);
  276. AssertEquals(Msg+': Annotation count',aArgCount,aFunc.Annotations.Count);
  277. if aHaveResult then
  278. AssertNotNull(Msg+': Have Result',aFunc.TypeDef.ResultType)
  279. else
  280. AssertNull(Msg+': Have no Result',aFunc.TypeDef.ResultType);
  281. end;
  282. class procedure TTestWITParser.AssertFunctionParam(const Msg: String; aParam: TWITFuncParam;const aName: String;
  283. aTypeKind: TWITTypeKind; aTypeName: string);
  284. begin
  285. AssertNotNull(Msg+': Have param',aParam);
  286. AssertEquals(Msg+': param name',aName,aParam.Name);
  287. AssertEquals(Msg+': param Type kind',aTypeKind,aParam.ParamType.Kind);
  288. end;
  289. class procedure TTestWITParser.AssertInterface(const Msg: String; aIntf: TWITInterface;const aName: String;
  290. aFuncCount: Integer; aTypeCount: Integer; aAnnotationCount: Integer);
  291. begin
  292. AssertNotNull(Msg+': Have Interface',aIntf);
  293. AssertEquals(Msg+': name',aName,aIntf.Name);
  294. AssertEquals(Msg+': function count',aFuncCount,aIntf.Functions.Count);
  295. AssertEquals(Msg+': Type count',aTypeCount,aIntf.Types.Count);
  296. AssertEquals(Msg+': Annotation count',aAnnotationCount,aIntf.Annotations.Count);
  297. end;
  298. class procedure TTestWITParser.AssertWorld(const Msg: String; aWorld: TWITWorld; const aWorldName: String; aExportCount,
  299. aImportCount, aUseCount, aTypeDefCount, aIncludeCount: Integer);
  300. begin
  301. AssertNotNull(Msg+': Have world',aWorld);
  302. AssertEquals(Msg+': name',aWorldName,aWorld.Name);
  303. AssertEquals(Msg+': export count',aExportCount,aWorld.Exported.Count);
  304. AssertEquals(Msg+': import count',aImportCount,aWorld.Imported.Count);
  305. AssertEquals(Msg+': use count',aUseCount,aWorld.UsesList.Count);
  306. AssertEquals(Msg+': type count',aTypeDefCount,aWorld.TypeDefs.Count);
  307. AssertEquals(Msg+': include count',aIncludeCount,aWorld.Includes.Count);
  308. end;
  309. class procedure TTestWITParser.AssertPackage(
  310. const Msg: String;
  311. aPackage: TWITPackage;
  312. aExpectedNamespace: string;
  313. aExpectedPackageName: string;
  314. aExpectedVersion: string;
  315. aExpectedWorldCount: Integer = 0;
  316. aExpectedImportCount: Integer = 0;
  317. aExpectedExportCount: Integer = 0;
  318. aExpectedUseCount: Integer = 0;
  319. aExpectedInterfaceCount: Integer = 0
  320. );
  321. begin
  322. AssertNotNull(Msg + ': Package object should exist', aPackage);
  323. AssertEquals(Msg + ': Namespace', aExpectedNamespace, aPackage.Namespace);
  324. AssertEquals(Msg + ': PackageName', aExpectedPackageName, aPackage.PackageName);
  325. AssertEquals(Msg + ': Version', aExpectedVersion, aPackage.Version);
  326. // Check that list objects themselves are created (common practice in constructors)
  327. AssertNotNull(Msg + ': ImportList object should exist', aPackage.ImportList);
  328. AssertEquals(Msg + ': ImportList count', aExpectedImportCount, aPackage.ImportList.Count);
  329. AssertNotNull(Msg + ': ExportList object should exist', aPackage.ExportList);
  330. AssertEquals(Msg + ': ExportList count', aExpectedExportCount, aPackage.ExportList.Count);
  331. AssertNotNull(Msg + ': UseStatements object should exist', aPackage.UseStatements);
  332. AssertEquals(Msg + ': UseStatements count', aExpectedUseCount, aPackage.UseStatements.Count);
  333. AssertNotNull(Msg + ': Interfaces list object should exist', aPackage.Interfaces);
  334. AssertEquals(Msg + ': Interfaces count', aExpectedInterfaceCount, aPackage.Interfaces.Count);
  335. end;
  336. function TTestWITParser.ParseWorld(const aWorldName: String; aExportCount, aImportCount, aUseCount, aTypeDefCount,
  337. aIncludeCount: Integer): TWITWorld;
  338. begin
  339. FDocument := FParser.ParseDocument;
  340. AssertNotNull('Have Document', FDocument);
  341. // Assert Package Details
  342. AssertNotNull('Have Package.', FDocument.DefaultPackage);
  343. AssertEquals('Have interface', 1, FDocument.DefaultPackage.Worlds.Count);
  344. Result := FDocument.DefaultPackage.Worlds[0];
  345. AssertWorld('World def', Result, aWorldName, aExportCount, aImportCount, aUseCount, aTypeDefCount, aIncludeCount);
  346. end;
  347. function TTestWITParser.ParseFunc(const aFuncName: String; aArgNames: array of string; aArgTypes: array of TWitTypeKind;
  348. aResultType: TWitTypeKind): TWITFunction;
  349. var
  350. LInterface: TWITInterface;
  351. i : Integer;
  352. lParam : TWITFuncParam;
  353. begin
  354. LInterface:=ParseInterface('funcs',1,0,0);
  355. AssertEquals('Have function',TWITFunction,LInterface.Functions[0].ClassType);
  356. Result:=LInterface.Functions[0];
  357. AssertEquals('function name',aFuncName,Result.Name);
  358. AssertNotNull('Function typedef',Result.TypeDef);
  359. AssertNotNull('Function params',Result.TypeDef.Parameters);
  360. AssertEquals('Args count',Length(aArgNames),Result.TypeDef.Parameters.Count);
  361. for I:=0 to Length(aArgNames)-1 do
  362. begin
  363. lParam:=Result.TypeDef.Parameters[i];
  364. AssertNotNull('Function param '+IntTostr(i),lParam);
  365. AssertEquals('Function param name'+IntTostr(i),aArgNames[i],lParam.Name);
  366. AssertNotNull('Have Function param type '+IntTostr(i),lParam.ParamType);
  367. AssertEquals('Function param type kind '+IntTostr(i),aArgTypes[i],lParam.ParamType.Kind);
  368. end;
  369. if aResultType=wtVoid then
  370. AssertNull('No result type',Result.TypeDef.ResultType)
  371. else
  372. begin
  373. AssertNotNull('have result type',Result.TypeDef.ResultType);
  374. AssertEquals('result type kind',aResultType,Result.TypeDef.ResultType.Kind)
  375. end;
  376. end;
  377. class function TTestWITParser.AssertResultType(const aMsg: string; aType: TWITTypeDef;const aName: String; aOKKind: TWITTypeKind;
  378. aErrorKind: TWitTypeKind; aIgnore: TResultIgnores): TWITResultType;
  379. var
  380. lRes : TWITResultType;
  381. begin
  382. AssertNotNull(aMsg+': have type',aType);
  383. AssertEquals(aMsg+': have name',aName,aType.Name);
  384. AssertNotNull(aMsg+': have typedef',aType.TypeDef);
  385. AssertEquals(aMsg+': have typedef',TWITResultType,aType.TypeDef.ClassType);
  386. lRes:=aType.TypeDef as TWITResultType;
  387. if riResult in aIgnore then
  388. AssertNull(aMsg+': no OK type',lRes.OkType)
  389. else
  390. begin
  391. AssertNotNull(aMsg+': OK type',lRes.OkType);
  392. AssertEquals(aMsg+': OK type kind',aOKKind,lRes.OkType.Kind);
  393. end;
  394. if riError in aIgnore then
  395. AssertNull(aMsg+': no Error type',lRes.ErrorType)
  396. else
  397. begin
  398. AssertNotNull(aMsg+': Error type',lRes.ErrorType);
  399. AssertEquals(aMsg+': Error type kind',aErrorKind,lRes.ErrorType.Kind);
  400. end;
  401. Result:=lRes;
  402. end;
  403. class function TTestWITParser.AssertOptionType(const aMsg: string; aType: TWITTypeDef;const aName: String; aOptionKind: TWITTypeKind
  404. ): TWITOptionType;
  405. var
  406. lOpt : TWITOptionType;
  407. begin
  408. AssertNotNull(aMsg+': have type',aType);
  409. AssertEquals(aMsg+': have name',aName,aType.Name);
  410. AssertNotNull(aMsg+': have typedef',aType.TypeDef);
  411. AssertEquals(aMsg+': have typedef',TWITOptionType,aType.TypeDef.ClassType);
  412. lopt:=aType.TypeDef as TWITOptionType;
  413. AssertNotNull(aMsg+': item type',lOpt.ItemType);
  414. AssertEquals(aMsg+': type kind',aOptionKind,lOpt.ItemType.Kind);
  415. Result:=lOpt;
  416. end;
  417. class function TTestWITParser.AssertStreamType(const aMsg: string; aType: TWITTypeDef;const aName: String; aStreamKind: TWITTypeKind
  418. ): TWITStreamType;
  419. var
  420. lStream : TWITStreamType;
  421. begin
  422. AssertNotNull(aMsg+': have type',aType);
  423. AssertEquals(aMsg+': have name',aName,aType.Name);
  424. AssertNotNull(aMsg+': have typedef',aType.TypeDef);
  425. AssertEquals(aMsg+': have typedef',TWITStreamType,aType.TypeDef.ClassType);
  426. lStream:=aType.TypeDef as TWITStreamType;
  427. AssertNotNull(aMsg+': item type',lStream.ItemType);
  428. AssertEquals(aMsg+': type kind',aStreamKind,lStream.ItemType.Kind);
  429. Result:=lStream;
  430. end;
  431. class function TTestWITParser.AssertFutureType(const aMsg: string; aType: TWITTypeDef;const aName: String; aFutureKind: TWITTypeKind
  432. ): TWITFutureType;
  433. var
  434. lFuture : TWITFutureType;
  435. begin
  436. AssertNotNull(aMsg+': have type',aType);
  437. AssertEquals(aMsg+': have name',aName,aType.Name);
  438. AssertNotNull(aMsg+': have typedef',aType.TypeDef);
  439. AssertEquals(aMsg+': have typedef',TWITFutureType,aType.TypeDef.ClassType);
  440. lFuture:=aType.TypeDef as TWitFutureType;
  441. AssertNotNull(aMsg+': item type',lFuture.ItemType);
  442. AssertEquals(aMsg+': type kind',aFutureKind,lFuture.ItemType.Kind);
  443. Result:=lFuture;
  444. end;
  445. class function TTestWITParser.AssertTupleType(const aMsg: string; aType: TWITTypeDef;const aName: String;
  446. aOptionKind: array of TWITTypeKind): TWITTupleType;
  447. var
  448. lTuple : TWITTupleType;
  449. I : Integer;
  450. S : String;
  451. begin
  452. AssertNotNull(aMsg+': have type',aType);
  453. AssertEquals(aMsg+': have name',aName,aType.Name);
  454. AssertNotNull(aMsg+': have typedef',aType.TypeDef);
  455. AssertEquals(aMsg+': have typedef',TWITTupleType,aType.TypeDef.ClassType);
  456. lTuple:=aType.TypeDef as TWITTupleType;
  457. AssertEquals(aMsg+': have correct count',Length(aOptionKind),lTuple.Items.Count);
  458. For I:=0 to Length(aOptionKind)-1 do
  459. begin
  460. S:=Format(': item[%d]',[i]);
  461. AssertNotNull(aMsg+S+' type ',lTuple.Items[i]);
  462. AssertEquals(aMsg+S+' kind',aOptionKind[i],lTuple.Items[i].Kind);
  463. end;
  464. Result:=lTuple;
  465. end;
  466. class function TTestWITParser.AssertFlagsType(const aMsg: string; aType: TWITTypeDef;const aName: String; aFlagNames: array of String
  467. ): TWITFlagsType;
  468. var
  469. lFlags : TWITFlagsType;
  470. I : Integer;
  471. S : String;
  472. begin
  473. AssertNotNull(aMsg+': have type',aType);
  474. AssertEquals(aMsg+': have name',aName,aType.Name);
  475. AssertNotNull(aMsg+': have typedef',aType.TypeDef);
  476. AssertEquals(aMsg+': have typedef',TWITFlagsType,aType.TypeDef.ClassType);
  477. lFlags:=aType.TypeDef as TWITFlagsType;
  478. AssertEquals(aMsg+': have correct count',Length(aFlagNames),lFlags.Flags.Count);
  479. For I:=0 to Length(aFlagNames)-1 do
  480. begin
  481. S:=Format(': item[%d]',[i]);
  482. AssertEquals(aMsg+S+' name',aFlagNames[i],lFlags.Flags[i]);
  483. end;
  484. Result:=lFlags;
  485. end;
  486. class function TTestWITParser.AssertVariantType(const aMsg: string; aType: TWITTypeDef;const aName: String; aVariantNames: array of String
  487. ): TWITVariantType;
  488. var
  489. lVariant : TWITVariantType;
  490. I : Integer;
  491. S : String;
  492. begin
  493. AssertNotNull(aMsg+': have type',aType);
  494. AssertEquals(aMsg+': have name',aName,aType.Name);
  495. AssertNotNull(aMsg+': have typedef',aType.TypeDef);
  496. AssertEquals(aMsg+': have typedef',TWITVariantType,aType.TypeDef.ClassType);
  497. lVariant:=aType.TypeDef as TWITVariantType;
  498. AssertEquals(aMsg+': have correct count',Length(aVariantNames),lVariant.Cases.Count);
  499. For I:=0 to Length(aVariantNames)-1 do
  500. begin
  501. S:=Format(': item[%d]',[i]);
  502. AssertEquals(aMsg+S+' name',aVariantNames[i],lVariant.Cases[i].Name);
  503. end;
  504. Result:=lVariant;
  505. end;
  506. class function TTestWITParser.AssertRecordType(const aMsg: string; aType: TWITTypeDef;const aName: String; aFieldNames: array of String;
  507. aFieldTypes: array of TWITTypeKind): TWITRecordType;
  508. var
  509. lRecord: TWITRecordType;
  510. I : Integer;
  511. S : String;
  512. begin
  513. AssertNotNull(aMsg+': have type',aType);
  514. AssertEquals(aMsg+': have name',aName,aType.Name);
  515. AssertNotNull(aMsg+': have typedef',aType.TypeDef);
  516. AssertEquals(aMsg+': have typedef',TWITRecordType,aType.TypeDef.ClassType);
  517. lRecord:=aType.TypeDef as TWITRecordType;
  518. AssertEquals(aMsg+': have correct count',Length(aFieldNames),lRecord.Fields.Count);
  519. For I:=0 to Length(aFieldNames)-1 do
  520. begin
  521. S:=Format(': field[%d]',[i]);
  522. AssertEquals(aMsg+S+' name',aFieldNames[i],lRecord.Fields[i].Name);
  523. AssertNotNull(aMsg+S+' type',lRecord.Fields[i].FieldType);
  524. AssertEquals(aMsg+S+' kind',aFieldTypes[i],lRecord.Fields[i].FieldType.Kind);
  525. end;
  526. Result:=lRecord;
  527. end;
  528. class function TTestWITParser.AssertResourceType(const aMsg: string; aType: TWITTypeDef;const aName: String; aConstructor: boolean;
  529. aFunctionNames: array of String): TWITResourceType;
  530. var
  531. lResource: TWITResourceType;
  532. I : Integer;
  533. S : String;
  534. lHaveConstructor : Boolean;
  535. begin
  536. lHaveConstructor:=False;
  537. AssertNotNull(aMsg+': have type',aType);
  538. AssertEquals(aMsg+': have name',aName,aType.Name);
  539. AssertNotNull(aMsg+': have typedef',aType.TypeDef);
  540. AssertEquals(aMsg+': have typedef',TWITResourceType,aType.TypeDef.ClassType);
  541. lResource:=aType.TypeDef as TWITResourceType;
  542. AssertEquals(aMsg+': have correct count',Length(aFunctionNames),lResource.Functions.Count);
  543. For I:=0 to Length(aFunctionNames)-1 do
  544. begin
  545. S:=Format(': function[%d]',[i]);
  546. AssertEquals(aMsg+S+' name',aFunctionNames[i],lResource.Functions[i].Name);
  547. if not lHaveConstructor then
  548. begin
  549. lHaveConstructor:=ffConstructor in lResource.Functions[i].TypeDef.Flags;
  550. if lHaveConstructor then
  551. AssertEquals(aMsg+': have name',aName,lResource.Functions[i].Name);
  552. end;
  553. end;
  554. Result:=lResource;
  555. end;
  556. class function TTestWITParser.AssertAliasType(const aMsg: string; aType: TWITTypeDef;const aName: String; aAliasName: String
  557. ): TWITIdentifierType;
  558. begin
  559. AssertNotNull(aMsg+': have type',aType);
  560. AssertEquals(aMsg+': have name',aName,aType.Name);
  561. AssertNotNull(aMsg+': have typedef',aType.TypeDef);
  562. AssertEquals(aMsg+': have typedef',TWITIdentifierType,aType.TypeDef.ClassType);
  563. Result:=aType.TypeDef as TWITIdentifierType;
  564. AssertEquals('Alias name ',aAliasName,Result.Name);
  565. end;
  566. class function TTestWITParser.AssertHandleType(const aMsg: string; aType: TWITTypeDef; const aName: String; aAliasName: String
  567. ): TWITHandleType;
  568. begin
  569. AssertNotNull(aMsg+': have type',aType);
  570. AssertEquals(aMsg+': have name',aName,aType.Name);
  571. AssertNotNull(aMsg+': have typedef',aType.TypeDef);
  572. AssertEquals(aMsg+': have typedef',TWITHandleType,aType.TypeDef.ClassType);
  573. Result:=aType.TypeDef as TWITHandleType;
  574. AssertEquals('Alias name ',aAliasName,Result.Name);
  575. end;
  576. class function TTestWITParser.AssertTypeDef(const Msg: String; aType: TWITType; aExpectedName: string;
  577. aExpectedUnderlyingKind: TWITTypeKind): TWITType;
  578. var
  579. lTypeDef : TWITTypeDef absolute aType;
  580. begin
  581. AssertNotNull(Msg + ': Have Type', aType);
  582. AssertEquals(Msg + ': Type is TypeDef', TWITTypeDef, aType.ClassType);
  583. AssertNotNull(Msg + ': Have Type.TypeDef', lTypeDef.Typedef);
  584. AssertEquals(Msg + ': Type alias name', aExpectedName, lTypeDef.Name);
  585. AssertEquals(Msg + ': Underlying type kind of alias', aExpectedUnderlyingKind, lTypeDef.Kind);
  586. Result:=lTypeDef.TypeDef;
  587. end;
  588. class function TTestWITParser.AssertListType(const aMsg: string; aTypeDef: TWitTypeDef;const aName: String; aElementKind: TWITTypeKind;
  589. aCount: Integer): TWitType;
  590. var
  591. lListDef : TWITListType;
  592. begin
  593. AssertEquals(aMsg+'type name',aName,aTypeDef.Name);
  594. AssertEquals(aMsg+'List type',wtList,aTypeDef.Kind);
  595. AssertEquals(aMsg+'Typedef class',TWITListType,aTypeDef.TypeDef.ClassType);
  596. lListDef:=aTypeDef.TypeDef as TWITListType;
  597. AssertEquals(aMsg+'List element type',aElementKind,lListDef.ItemType.Kind);
  598. AssertEquals(aMsg+'List element count',aCount,lListDef.ItemCount);
  599. Result:=lListDef.ItemType;
  600. end;
  601. class function TTestWITParser.AssertEnumType(const aMsg: String; aType: TWITTypeDef;const aName: String; aValues: array of string
  602. ): TWITEnumType;
  603. var
  604. lEnum : TWITEnumType;
  605. I : integer;
  606. begin
  607. AssertTypeDef(aMsg,aType,aName,wtEnum);
  608. AssertEquals(aMsg+': name',aName,aType.Name);
  609. AssertEquals(aMsg+': type',TWITEnumType,aType.TypeDef.ClassType);
  610. lEnum:=aType.TypeDef as TWITEnumType;
  611. AssertEquals(aMsg+': case count',Length(aValues),lEnum.Cases.Count);
  612. For I:=0 to Length(aValues)-1 do
  613. AssertEquals(aMsg+': case '+IntToStr(i),aValues[i],lEnum.Cases[i]);
  614. Result:=lEnum;
  615. end;
  616. { ---------------------------------------------------------------------
  617. Parsing aids
  618. ---------------------------------------------------------------------}
  619. function TTestWITParser.ParseInterface(const aName : String; aFunctionCount, aTypeCount, aAnnotationCount : integer) : TWITInterface;
  620. begin
  621. FDocument := FParser.ParseDocument;
  622. AssertNotNull('Have Document', FDocument);
  623. // Assert Package Details
  624. AssertNotNull('Have Package.', FDocument.DefaultPackage);
  625. AssertEquals('Have interface', 1, FDocument.DefaultPackage.Interfaces.Count);
  626. Result := FDocument.DefaultPackage.Interfaces[0];
  627. AssertInterface('Interface def', Result, aName, aFunctionCount,aTYpeCount, aAnnotationCount);
  628. end;
  629. function TTestWITParser.ParseType(const aInterFaceName,aTypeName: String): TWITTypeDef;
  630. var
  631. LInterface: TWITInterface;
  632. begin
  633. LInterface:=ParseInterface(aInterfaceName,0,1,0);
  634. AssertEquals('Have Type',TWITTypeDef,LInterface.Types[0].ClassType);
  635. Result:=LInterface.Types[0] as TWITTypeDef;
  636. AssertEquals('type name',aTypeName,Result.Name);
  637. end;
  638. { ---------------------------------------------------------------------
  639. Actual tests
  640. ---------------------------------------------------------------------}
  641. procedure TTestWITParser.TestParseExitInterfaceDocument;
  642. const
  643. WIT_CONTENT =
  644. '@since(version = 0.2.0)' + sLineBreak +
  645. 'interface exit {' + sLineBreak +
  646. ' @since(version = 0.2.0)' + sLineBreak +
  647. ' exit: func(status: result);' + sLineBreak +
  648. sLineBreak +
  649. ' @unstable(feature = cli-exit-with-code)' + sLineBreak +
  650. ' exit-with-code: func(status-code: u8);' + sLineBreak +
  651. '}';
  652. var
  653. LInterface: TWITInterface;
  654. LFunc: TWITFunction;
  655. LParam: TWITFuncParam;
  656. LParamType: TWITType;
  657. begin
  658. InitParser(WIT_CONTENT);
  659. AssertNotNull('Parser should be created.', FParser);
  660. FDocument := FParser.ParseDocument;
  661. AssertNotNull('ParseDocument should return a valid TWITDocument.', FDocument);
  662. // Document should contain one interface
  663. AssertEquals('Document should contain one interface.', 1, FDocument.Interfaces.Count);
  664. lInterface:=FDocument.Interfaces[0];
  665. AssertInterface('Exit interface',lInterface,'exit',2,0,1);
  666. AssertAnnotation('Intf annotation',LInterface.Annotations[0],'since',['version','0.2.0']);
  667. // --- Test Function 0: "exit" ---
  668. lFunc:=LInterface.Functions[0];
  669. AssertFunction('First exit func',lFunc,'exit',1,False,1);
  670. AssertAnnotation('First exit func annotation',lFunc.Annotations[0],'since',['version','0.2.0']);
  671. LParam := LFunc.TypeDef.Parameters[0];
  672. AssertFunctionParam('Parameter 0 of function "exit"',LParam,'status',wtResult,'');
  673. lParamType:=lParam.ParamType;
  674. AssertEquals('Parameter status type',TWITResultType,LParamType.ClassType);
  675. AssertNull('OkType for shorthand "result" should be nil or an empty type representation.', (LParamType as TWITResultType).OkType);
  676. AssertNull('ErrorType for shorthand "result" should be nil or an empty type representation.', (LParamType as TWITResultType).ErrorType);
  677. // --- Test Function 1: "exit-with-code" ---
  678. LFunc := LInterface.Functions[1];
  679. AssertFunction('Second exit func',lFunc,'exit-with-code',1,False,1);
  680. AssertAnnotation('Second exit func annotation',lFunc.Annotations[0],'unstable',['feature','cli-exit-with-code']);
  681. LParam := LFunc.TypeDef.Parameters[0];
  682. AssertFunctionParam('Parameter 0 of function "exit-with-code"',LParam,'status-code',wtU8,'');
  683. end;
  684. procedure TTestWITParser.TestSimpleTypes;
  685. const
  686. WIT_CONTENT =
  687. 'package foo:types;' + sLineBreak +
  688. sLineBreak +
  689. 'interface types {' + sLineBreak +
  690. ' type t1 = u8;' + sLineBreak +
  691. ' type t2 = u16;' + sLineBreak +
  692. ' type t3 = u32;' + sLineBreak +
  693. ' type t4 = u64;' + sLineBreak +
  694. ' type t5 = s8;' + sLineBreak +
  695. ' type t6 = s16;' + sLineBreak +
  696. ' type t7 = s32;' + sLineBreak +
  697. ' type t8 = s64;' + sLineBreak +
  698. ' type t9a = f32;' + sLineBreak +
  699. ' type t9b = f32;' + sLineBreak + // Duplicate type kind, different name
  700. ' type t10a = f64;' + sLineBreak +
  701. ' type t10b = f64;' + sLineBreak + // Duplicate type kind, different name
  702. ' type t11 = char;' + sLineBreak + // Assuming char maps to wtU32
  703. ' type t12 = string;' + sLineBreak +
  704. '}';
  705. var
  706. LInterface: TWITInterface;
  707. begin
  708. InitParser(WIT_CONTENT);
  709. LInterface := ParseInterface('types',0,14,0);
  710. AssertTypeDef('Type t1 = u8', LInterface.Types[0], 't1', wtU8);
  711. AssertTypeDef('Type t2 = u16', LInterface.Types[1], 't2', wtU16);
  712. AssertTypeDef('Type t3 = u32', LInterface.Types[2], 't3', wtU32);
  713. AssertTypeDef('Type t4 = u64', LInterface.Types[3], 't4', wtU64);
  714. AssertTypeDef('Type t5 = s8', LInterface.Types[4], 't5', wtS8);
  715. AssertTypeDef('Type t6 = s16', LInterface.Types[5], 't6', wtS16);
  716. AssertTypeDef('Type t7 = s32', LInterface.Types[6], 't7', wtS32);
  717. AssertTypeDef('Type t8 = s64', LInterface.Types[7], 't8', wtS64);
  718. AssertTypeDef('Type t9a = f32', LInterface.Types[8], 't9a', wtFloat32);
  719. AssertTypeDef('Type t9b = f32', LInterface.Types[9], 't9b', wtFloat32);
  720. AssertTypeDef('Type t10a = f64', LInterface.Types[10], 't10a', wtFloat64);
  721. AssertTypeDef('Type t10b = f64', LInterface.Types[11], 't10b', wtFloat64);
  722. AssertTypeDef('Type t11 = char', LInterface.Types[12], 't11', wtChar);
  723. AssertTypeDef('Type t12 = string', LInterface.Types[13], 't12', wtString);
  724. end;
  725. procedure TTestWITParser.TestListType;
  726. const
  727. WIT_CONTENT = 'list<char>';
  728. var
  729. lTypeDef : TWITTypeDef;
  730. begin
  731. InitParser(WrapTypeDef(WIT_CONTENT, true));
  732. lTypeDef:=ParseType('types','a');
  733. AssertListType('List',lTypeDef,'a',wtChar);
  734. end;
  735. procedure TTestWITParser.TestListListType;
  736. const
  737. WIT_CONTENT = 'list<list<list<t32>>>';
  738. var
  739. lTypeDef : TWITTypeDef;
  740. lItem : TWITType;
  741. lList : TWITListType absolute litem;
  742. lIdent : TWITIdentifierType;
  743. begin
  744. InitParser(WrapTypeDef(WIT_CONTENT, true));
  745. lTypeDef:=ParseType('types','a');
  746. lItem:=AssertListType('List',lTypeDef,'a',wtList);
  747. AssertEquals('Item is list class',TWITListType,lItem.ClassType);
  748. AssertEquals('Item.Item is list class',TWITListType,lList.ItemType.ClassType);
  749. lItem:=lList.ItemType;
  750. AssertEquals('Item.Item.Item is identifier class',TWITIdentifierType,lList.ItemType.ClassType);
  751. lIdent:=lList.ItemType as TWITIdentifierType;
  752. AssertEquals('Item.Item.Item name','t32',lIdent.Name);
  753. end;
  754. procedure TTestWITParser.TestListSized;
  755. const
  756. WIT_CONTENT = 'list<u32, 4>';
  757. var
  758. lTypeDef : TWITTypeDef;
  759. begin
  760. InitParser(WrapTypeDef(WIT_CONTENT,True));
  761. lTypeDef:=ParseType('types','a');
  762. AssertListType('List',lTypeDef,'a',wtU32,4);
  763. end;
  764. procedure TTestWITParser.TestListSizedListSized;
  765. const
  766. WIT_CONTENT = 'list<list<u32, 4>, 2>';
  767. var
  768. lTypeDef : TWITTypeDef;
  769. lItem : TWITType;
  770. lList : TWITListType absolute lItem;
  771. begin
  772. InitParser(WrapTypeDef(WIT_CONTENT, true));
  773. lTypeDef:=ParseType('types','a');
  774. lItem:=AssertListType('List',lTypeDef,'a',wtList,2);
  775. AssertEquals('Item class',TWITListType,lItem.ClassType);
  776. AssertEquals('List list item',wtu32,lList.ItemType.Kind);
  777. AssertEquals('List list item count',4,lList.ItemCount);
  778. end;
  779. procedure TTestWITParser.TestEnum;
  780. const
  781. WIT_CONTENT = 'enum a {one,two,three}';
  782. var
  783. lTypeDef : TWITTypeDef;
  784. begin
  785. InitParser(WrapTypeDef(WIT_CONTENT));
  786. lTypeDef:=ParseType('types','a');
  787. AssertEnumType('Enum type',lTypeDef,'a',['one','two','three']);
  788. end;
  789. procedure TTestWITParser.TestEnumEndWithComma;
  790. const
  791. WIT_CONTENT = 'enum a {one,two,three,}';
  792. var
  793. lTypeDef : TWITTypeDef;
  794. begin
  795. InitParser(WrapTypeDef(WIT_CONTENT));
  796. lTypeDef:=ParseType('types','a');
  797. AssertEnumType('Enum type',lTypeDef,'a',['one','two','three']);
  798. end;
  799. procedure TTestWITParser.TestResultEmpty;
  800. const
  801. WIT_CONTENT = 'result';
  802. var
  803. lTypeDef : TWITTypeDef;
  804. begin
  805. InitParser(WrapTypeDef(WIT_CONTENT,True));
  806. lTypeDef:=ParseType('types','a');
  807. AssertResultType('Result type',LTypeDef,'a',wtu32,wtu8,[riResult,riError]);
  808. end;
  809. procedure TTestWITParser.TestResultOneType;
  810. const
  811. WIT_CONTENT = 'result<u32>';
  812. var
  813. lTypeDef : TWITTypeDef;
  814. begin
  815. InitParser(WrapTypeDef(WIT_CONTENT,True));
  816. lTypeDef:=ParseType('types','a');
  817. AssertResultType('Result type',LTypeDef,'a',wtu32,wtu8,[riError]);
  818. end;
  819. procedure TTestWITParser.TestResultTwoTypes;
  820. const
  821. WIT_CONTENT = 'result<u32,u8>';
  822. var
  823. lTypeDef : TWITTypeDef;
  824. begin
  825. InitParser(WrapTypeDef(WIT_CONTENT,True));
  826. lTypeDef:=ParseType('types','a');
  827. AssertResultType('Result type',LTypeDef,'a',wtu32,wtu8,[]);
  828. end;
  829. procedure TTestWITParser.TestResultOneIgnoredTyoe;
  830. const
  831. WIT_CONTENT = 'result<_,u32>';
  832. var
  833. lTypeDef : TWITTypeDef;
  834. begin
  835. InitParser(WrapTypeDef(WIT_CONTENT,True));
  836. lTypeDef:=ParseType('types','a');
  837. AssertResultType('Result type',LTypeDef,'a',wtu32,wtu32,[riResult]);
  838. end;
  839. procedure TTestWITParser.TestOption;
  840. const
  841. WIT_CONTENT = 'option<u32>';
  842. var
  843. lTypeDef : TWITTypeDef;
  844. begin
  845. InitParser(WrapTypeDef(WIT_CONTENT,True));
  846. LTypeDef:=ParseType('types','a');
  847. AssertOptionType('Option type',LTypeDef,'a',wtu32);
  848. end;
  849. procedure TTestWITParser.TestStream;
  850. const
  851. WIT_CONTENT = 'stream<u32>';
  852. var
  853. lTypeDef : TWITTypeDef;
  854. begin
  855. InitParser(WrapTypeDef(WIT_CONTENT,True));
  856. LTypeDef:=ParseType('types','a');
  857. AssertStreamType('Stream type',LTypeDef,'a',wtu32);
  858. end;
  859. procedure TTestWITParser.TestStreamEmpty;
  860. const
  861. WIT_CONTENT = 'stream';
  862. var
  863. lTypeDef : TWITTypeDef;
  864. begin
  865. InitParser(WrapTypeDef(WIT_CONTENT,True));
  866. LTypeDef:=ParseType('types','a');
  867. AssertStreamType('Stream type',LTypeDef,'a',wtVoid);
  868. end;
  869. procedure TTestWITParser.TestFuture;
  870. const
  871. WIT_CONTENT = 'future<u32>';
  872. var
  873. lTypeDef : TWITTypeDef;
  874. begin
  875. InitParser(WrapTypeDef(WIT_CONTENT,True));
  876. LTypeDef:=ParseType('types','a');
  877. AssertFutureType('Future type',LTypeDef,'a',wtu32);
  878. end;
  879. procedure TTestWITParser.TestNestedFuture;
  880. const
  881. WIT_CONTENT = 'option<stream<future>>';
  882. var
  883. lTypeDef : TWITTypeDef;
  884. lOpt : TWITOptionType;
  885. lStream : TWITStreamType;
  886. begin
  887. InitParser(WrapTypeDef(WIT_CONTENT,True));
  888. LTypeDef:=ParseType('types','a');
  889. lOpt:=AssertOptionType('Option type',LTypeDef,'a',wtStream);
  890. AssertEquals('Stream type',TWITStreamType,lOpt.ItemType.ClassType);
  891. lStream:=lOpt.ItemType as TWITStreamType;
  892. AssertEquals('Future type',TWITFutureType,lStream.ItemType.Classtype);
  893. end;
  894. procedure TTestWITParser.TestFutureEmpty;
  895. const
  896. WIT_CONTENT = 'future';
  897. var
  898. lTypeDef : TWITTypeDef;
  899. begin
  900. InitParser(WrapTypeDef(WIT_CONTENT,True));
  901. LTypeDef:=ParseType('types','a');
  902. AssertFutureType('Future type',LTypeDef,'a',wtVoid);
  903. end;
  904. procedure TTestWITParser.TestTupleEmpty;
  905. const
  906. WIT_CONTENT = 'tuple<>';
  907. var
  908. lTypeDef : TWITTypeDef;
  909. begin
  910. InitParser(WrapTypeDef(WIT_CONTENT,True));
  911. LTypeDef:=ParseType('types','a');
  912. AssertTupleType('Tuple type',LTypeDef,'a',[]);
  913. end;
  914. procedure TTestWITParser.TestTuple1;
  915. const
  916. WIT_CONTENT = 'tuple<u32>';
  917. var
  918. lTypeDef : TWITTypeDef;
  919. begin
  920. InitParser(WrapTypeDef(WIT_CONTENT,True));
  921. LTypeDef:=ParseType('types','a');
  922. AssertTupleType('Tuple type',LTypeDef,'a',[wtu32]);
  923. end;
  924. procedure TTestWITParser.TestTuple2;
  925. const
  926. WIT_CONTENT = 'tuple<u32, u64>';
  927. var
  928. lTypeDef : TWITTypeDef;
  929. begin
  930. InitParser(WrapTypeDef(WIT_CONTENT,True));
  931. LTypeDef:=ParseType('types','a');
  932. AssertTupleType('Tuple type',LTypeDef,'a',[wtu32,wtu64]);
  933. end;
  934. procedure TTestWITParser.TestTuple3;
  935. const
  936. WIT_CONTENT = 'tuple<u32, u64, u8>';
  937. var
  938. lTypeDef : TWITTypeDef;
  939. begin
  940. InitParser(WrapTypeDef(WIT_CONTENT,True));
  941. LTypeDef:=ParseType('types','a');
  942. AssertTupleType('Tuple type',LTypeDef,'a',[wtu32,wtu64,wtu8]);
  943. end;
  944. procedure TTestWITParser.TestTupleComma;
  945. const
  946. WIT_CONTENT = 'tuple<u32,>';
  947. var
  948. LTypeDef : TWITTypeDef;
  949. begin
  950. InitParser(WrapTypeDef(WIT_CONTENT,True));
  951. LTypeDef:=ParseType('types','a');
  952. AssertTupleType('Tuple type',LTypeDef,'a',[wtU32]);
  953. end;
  954. procedure TTestWITParser.TestFlagsEmpty;
  955. const
  956. WIT_CONTENT = 'flags a {}';
  957. var
  958. LTypeDef : TWITTypeDef;
  959. begin
  960. InitParser(WrapTypeDef(WIT_CONTENT));
  961. LTypeDef:=ParseType('types','a');
  962. AssertFlagsType('Tuple type',LTypeDef,'a',[]);
  963. end;
  964. procedure TTestWITParser.TestFlags1;
  965. const
  966. WIT_CONTENT = 'flags a {a}';
  967. var
  968. LTypeDef : TWITTypeDef;
  969. begin
  970. InitParser(WrapTypeDef(WIT_CONTENT));
  971. LTypeDef:=ParseType('types','a');
  972. AssertFlagsType('Tuple type',LTypeDef,'a',['a']);
  973. end;
  974. procedure TTestWITParser.TestFlags2;
  975. const
  976. WIT_CONTENT = 'flags a {a, b}';
  977. var
  978. LTypeDef : TWITTypeDef;
  979. begin
  980. InitParser(WrapTypeDef(WIT_CONTENT));
  981. LTypeDef:=ParseType('types','a');
  982. AssertFlagsType('Tuple type',LTypeDef,'a',['a','b']);
  983. end;
  984. procedure TTestWITParser.TestFlags3;
  985. const
  986. WIT_CONTENT = 'flags a {a, b, c}';
  987. var
  988. LTypeDef : TWITTypeDef;
  989. begin
  990. InitParser(WrapTypeDef(WIT_CONTENT));
  991. LTypeDef:=ParseType('types','a');
  992. AssertFlagsType('Tuple type',LTypeDef,'a',['a','b','c']);
  993. end;
  994. procedure TTestWITParser.TestFlagsComma;
  995. const
  996. WIT_CONTENT = 'flags a {a, b, c, }';
  997. var
  998. LTypeDef : TWITTypeDef;
  999. begin
  1000. InitParser(WrapTypeDef(WIT_CONTENT));
  1001. LTypeDef:=ParseType('types','a');
  1002. AssertFlagsType('Tuple type',LTypeDef,'a',['a','b','c']);
  1003. end;
  1004. procedure TTestWITParser.TestVariant1;
  1005. const
  1006. WIT_CONTENT = 'variant a { a }';
  1007. var
  1008. LTypeDef : TWITTypeDef;
  1009. begin
  1010. InitParser(WrapTypeDef(WIT_CONTENT));
  1011. LTypeDef:=ParseType('types','a');
  1012. AssertVariantType('Variant type',LTypeDef,'a',['a']);
  1013. end;
  1014. procedure TTestWITParser.TestVariant2;
  1015. const
  1016. WIT_CONTENT = 'variant a { a, b }';
  1017. var
  1018. LTypeDef : TWITTypeDef;
  1019. begin
  1020. InitParser(WrapTypeDef(WIT_CONTENT));
  1021. LTypeDef:=ParseType('types','a');
  1022. AssertVariantType('Variant type',LTypeDef,'a',['a','b']);
  1023. end;
  1024. procedure TTestWITParser.TestVariant2Comma;
  1025. const
  1026. WIT_CONTENT = 'variant a { a, b, }';
  1027. var
  1028. LTypeDef : TWITTypeDef;
  1029. begin
  1030. InitParser(WrapTypeDef(WIT_CONTENT));
  1031. LTypeDef:=ParseType('types','a');
  1032. AssertVariantType('Variant type',LTypeDef,'a',['a','b']);
  1033. end;
  1034. (*
  1035. variant t36 { a, b(u32), }
  1036. variant t37 { a, b(option<u32>), }
  1037. *)
  1038. procedure TTestWITParser.TestVariantTypedSimple;
  1039. const
  1040. WIT_CONTENT = 'variant a { a, b(u32) }';
  1041. var
  1042. LTypeDef : TWITTypeDef;
  1043. begin
  1044. InitParser(WrapTypeDef(WIT_CONTENT));
  1045. LTypeDef:=ParseType('types','a');
  1046. AssertVariantType('Variant type',LTypeDef,'a',['a','b']);
  1047. end;
  1048. procedure TTestWITParser.TestVariantTypedSimpleComma;
  1049. const
  1050. WIT_CONTENT = 'variant a { a, b(u32), }';
  1051. var
  1052. LTypeDef : TWITTypeDef;
  1053. begin
  1054. InitParser(WrapTypeDef(WIT_CONTENT));
  1055. LTypeDef:=ParseType('types','a');
  1056. AssertVariantType('Variant type',LTypeDef,'a',['a','b']);
  1057. end;
  1058. procedure TTestWITParser.TestVariantTypedComplex;
  1059. const
  1060. WIT_CONTENT = 'variant a { a, b(option<u32>) }';
  1061. var
  1062. LTypeDef : TWITTypeDef;
  1063. begin
  1064. InitParser(WrapTypeDef(WIT_CONTENT));
  1065. LTypeDef:=ParseType('types','a');
  1066. AssertVariantType('Variant type',LTypeDef,'a',['a','b']);
  1067. end;
  1068. procedure TTestWITParser.TestRecordEmpty;
  1069. const
  1070. WIT_CONTENT = 'record a {}';
  1071. var
  1072. LTypeDef : TWITTypeDef;
  1073. begin
  1074. InitParser(WrapTypeDef(WIT_CONTENT));
  1075. LTypeDef:=ParseType('types','a');
  1076. AssertRecordType('Record type',LTypeDef,'a',[],[]);
  1077. end;
  1078. procedure TTestWITParser.TestRecord1;
  1079. const
  1080. WIT_CONTENT = 'record a { a: u32 }';
  1081. var
  1082. LTypeDef : TWITTypeDef;
  1083. begin
  1084. InitParser(WrapTypeDef(WIT_CONTENT));
  1085. LTypeDef:=ParseType('types','a');
  1086. AssertRecordType('Record type',LTypeDef,'a',['a'],[wtU32]);
  1087. end;
  1088. procedure TTestWITParser.TestRecord2;
  1089. const
  1090. WIT_CONTENT = 'record a { a: u32, b: u64 }';
  1091. var
  1092. LTypeDef : TWITTypeDef;
  1093. begin
  1094. InitParser(WrapTypeDef(WIT_CONTENT));
  1095. LTypeDef:=ParseType('types','a');
  1096. AssertRecordType('Record type',LTypeDef,'a',['a','b'],[wtU32,wtU64]);
  1097. end;
  1098. procedure TTestWITParser.TestRecord2Comma;
  1099. const
  1100. WIT_CONTENT = 'record a { a: u32, b: u64, }';
  1101. var
  1102. LTypeDef : TWITTypeDef;
  1103. begin
  1104. InitParser(WrapTypeDef(WIT_CONTENT));
  1105. LTypeDef:=ParseType('types','a');
  1106. AssertRecordType('Record type',LTypeDef,'a',['a','b'],[wtU32,wtU64]);
  1107. end;
  1108. procedure TTestWITParser.TestRecordRecordName;
  1109. const
  1110. WIT_CONTENT = 'record %record { a: u32, b: u64, }';
  1111. var
  1112. LTypeDef : TWITTypeDef;
  1113. begin
  1114. InitParser(WrapTypeDef(WIT_CONTENT));
  1115. LTypeDef:=ParseType('types','record');
  1116. AssertRecordType('Record type',LTypeDef,'record',['a','b'],[wtU32,wtU64]);
  1117. end;
  1118. procedure TTestWITParser.TestAlias;
  1119. const
  1120. WIT_CONTENT = 'b';
  1121. var
  1122. LTypeDef : TWITTypeDef;
  1123. begin
  1124. InitParser(WrapTypeDef(WIT_CONTENT,True));
  1125. LTypeDef:=ParseType('types','a');
  1126. AssertAliasType('Alias type',LTypeDef,'a','b');
  1127. end;
  1128. procedure TTestWITParser.TestBorrowedHandle;
  1129. const
  1130. WIT_CONTENT = 'borrow<b>';
  1131. var
  1132. LTypeDef : TWITTypeDef;
  1133. lIdent : TWITHandleType;
  1134. begin
  1135. InitParser(WrapTypeDef(WIT_CONTENT,True));
  1136. LTypeDef:=ParseType('types','a');
  1137. lIdent:=AssertHandleType(' type',LTypeDef,'a','b');
  1138. AssertTrue('Borrowed',lIdent.Borrowed);
  1139. end;
  1140. procedure TTestWITParser.TestResourceEmpty;
  1141. const
  1142. WIT_CONTENT = 'resource a;';
  1143. var
  1144. LTypeDef : TWITTypeDef;
  1145. begin
  1146. InitParser(WrapTypeDef(WIT_CONTENT));
  1147. LTypeDef:=ParseType('types','a');
  1148. AssertResourceType('Resource type',LTypeDef,'a',false, []);
  1149. end;
  1150. procedure TTestWITParser.TestResourceEmpty2;
  1151. const
  1152. WIT_CONTENT = 'resource a {}';
  1153. var
  1154. LTypeDef : TWITTypeDef;
  1155. begin
  1156. InitParser(WrapTypeDef(WIT_CONTENT));
  1157. LTypeDef:=ParseType('types','a');
  1158. AssertResourceType('Resource type',LTypeDef,'a',false, []);
  1159. end;
  1160. procedure TTestWITParser.TestResourceConstructor;
  1161. const
  1162. WIT_CONTENT = 'resource a { constructor (c:u8); }';
  1163. var
  1164. LTypeDef : TWITTypeDef;
  1165. begin
  1166. InitParser(WrapTypeDef(WIT_CONTENT));
  1167. LTypeDef:=ParseType('types','a');
  1168. AssertResourceType('Resource type',LTypeDef,'a',true, ['a']);
  1169. end;
  1170. procedure TTestWITParser.TestResourceOneMethod;
  1171. const
  1172. WIT_CONTENT = 'resource a { write : func (c:u8); }';
  1173. var
  1174. LTypeDef : TWITTypeDef;
  1175. begin
  1176. InitParser(WrapTypeDef(WIT_CONTENT));
  1177. LTypeDef:=ParseType('types','a');
  1178. AssertResourceType('Resource type',LTypeDef,'a',true, ['write']);
  1179. end;
  1180. procedure TTestWITParser.TestResourceStaticMethod;
  1181. const
  1182. WIT_CONTENT = 'resource a { write : static func (c:u8); }';
  1183. var
  1184. LTypeDef : TWITTypeDef;
  1185. lRes : TWITResourceType;
  1186. begin
  1187. InitParser(WrapTypeDef(WIT_CONTENT));
  1188. LTypeDef:=ParseType('types','a');
  1189. lRes:=AssertResourceType('Resource type',LTypeDef,'a',true, ['write']);
  1190. AssertTrue('Function marked static',(ffStatic in lRes.Functions[0].TypeDef.Flags));
  1191. end;
  1192. procedure TTestWITParser.TestResourceAsyncMethod;
  1193. const
  1194. WIT_CONTENT = 'resource a { write : async func (c:u8); }';
  1195. var
  1196. LTypeDef : TWITTypeDef;
  1197. lRes : TWITResourceType;
  1198. begin
  1199. InitParser(WrapTypeDef(WIT_CONTENT));
  1200. LTypeDef:=ParseType('types','a');
  1201. lRes:=AssertResourceType('Resource type',LTypeDef,'a',true, ['write']);
  1202. AssertTrue('Function marked static',(ffAsync in lRes.Functions[0].TypeDef.Flags));
  1203. end;
  1204. procedure TTestWITParser.TestResourceTwoMethods;
  1205. const
  1206. WIT_CONTENT = 'resource a { '+sLineBreak+
  1207. ' read : func (c:u8) -> list<u8>; '+sLineBreak+
  1208. ' write : func (c : list<u8>); '+sLineBreak+
  1209. '}';
  1210. var
  1211. LTypeDef : TWITTypeDef;
  1212. begin
  1213. InitParser(WrapTypeDef(WIT_CONTENT));
  1214. LTypeDef:=ParseType('types','a');
  1215. AssertResourceType('Resource type',LTypeDef,'a',false, ['read','write']);
  1216. end;
  1217. procedure TTestWITParser.TestResourceOneMethodAndConstructor;
  1218. const
  1219. WIT_CONTENT = 'resource a { '+sLineBreak+
  1220. ' read : func (c:u8) -> list<u8>; '+sLineBreak+
  1221. ' constructor (c : list<u8>); '+sLineBreak+
  1222. '}';
  1223. var
  1224. LTypeDef : TWITTypeDef;
  1225. begin
  1226. InitParser(WrapTypeDef(WIT_CONTENT));
  1227. LTypeDef:=ParseType('types','a');
  1228. AssertResourceType('Resource type',LTypeDef,'a',true, ['read','a']);
  1229. end;
  1230. procedure TTestWITParser.TestUseIdentifier;
  1231. const
  1232. WIT_CONTENT = 'use a;';
  1233. var
  1234. lUse : TWITTopLevelUse;
  1235. begin
  1236. InitParser(WIT_CONTENT);
  1237. FDocument := FParser.ParseDocument;
  1238. AssertEquals('Uses count', 1, FDocument.UseStatements.Count);
  1239. lUse:=FDocument.UseStatements[0];
  1240. AssertUse('Simple use',lUse,'','','a','',[]);
  1241. end;
  1242. procedure TTestWITParser.TestUseIdentifierAs;
  1243. const
  1244. WIT_CONTENT = 'use a as b;';
  1245. var
  1246. lUse : TWITTopLevelUse;
  1247. begin
  1248. InitParser(WIT_CONTENT);
  1249. FDocument := FParser.ParseDocument;
  1250. AssertEquals('Uses count', 1, FDocument.UseStatements.Count);
  1251. lUse:=FDocument.UseStatements[0];
  1252. AssertUse('Simple use',lUse,'','','a','b',[]);
  1253. end;
  1254. procedure TTestWITParser.TestUseFullIdentifier;
  1255. const
  1256. WIT_CONTENT = 'use d:c/a;';
  1257. var
  1258. lUse : TWITTopLevelUse;
  1259. begin
  1260. InitParser(WIT_CONTENT);
  1261. FDocument := FParser.ParseDocument;
  1262. AssertEquals('Uses count', 1, FDocument.UseStatements.Count);
  1263. lUse:=FDocument.UseStatements[0];
  1264. AssertUse('Full use',lUse,'c','','a','',['d']);
  1265. end;
  1266. procedure TTestWITParser.TestUseFullIdentifierVersion;
  1267. const
  1268. WIT_CONTENT = 'use d:c/[email protected];';
  1269. var
  1270. lUse : TWITTopLevelUse;
  1271. begin
  1272. InitParser(WIT_CONTENT);
  1273. FDocument := FParser.ParseDocument;
  1274. AssertEquals('Uses count', 1, FDocument.UseStatements.Count);
  1275. lUse:=FDocument.UseStatements[0];
  1276. AssertUse('Full use',lUse,'c','1.1.1','a','',['d']);
  1277. end;
  1278. procedure TTestWITParser.TestUseFullIdentifierAs;
  1279. const
  1280. WIT_CONTENT = 'use d:c/a as b;';
  1281. var
  1282. lUse : TWITTopLevelUse;
  1283. begin
  1284. InitParser(WIT_CONTENT);
  1285. FDocument := FParser.ParseDocument;
  1286. AssertEquals('Uses count', 1, FDocument.UseStatements.Count);
  1287. lUse:=FDocument.UseStatements[0];
  1288. AssertUse('Full use',lUse,'c','','a','b',['d']);
  1289. end;
  1290. procedure TTestWITParser.TestUseFullIdentifierVersionAs;
  1291. const
  1292. WIT_CONTENT = 'use d:c/[email protected] as b;';
  1293. var
  1294. lUse : TWITTopLevelUse;
  1295. begin
  1296. InitParser(WIT_CONTENT);
  1297. FDocument := FParser.ParseDocument;
  1298. AssertEquals('Uses count', 1, FDocument.UseStatements.Count);
  1299. lUse:=FDocument.UseStatements[0];
  1300. AssertUse('Full use',lUse,'c','1.1.1','a','b',['d']);
  1301. end;
  1302. procedure TTestWITParser.TestParseFunctionEmpty;
  1303. const
  1304. WIT_CONTENT = '';
  1305. begin
  1306. InitParser(WrapFunc(WIT_CONTENT));
  1307. ParseFunc('a',[],[],wtVoid);
  1308. end;
  1309. procedure TTestWITParser.TestParseFunctionEmptyResult;
  1310. const
  1311. WIT_CONTENT = '';
  1312. begin
  1313. InitParser(WrapFunc(WIT_CONTENT,'u8'));
  1314. ParseFunc('a',[],[],wtU8);
  1315. end;
  1316. procedure TTestWITParser.TestParseFunctionOneParam;
  1317. const
  1318. WIT_CONTENT = 'b:u8';
  1319. begin
  1320. InitParser(WrapFunc(WIT_CONTENT));
  1321. ParseFunc('a',['b'],[wtU8],wtVoid);
  1322. end;
  1323. procedure TTestWITParser.TestParseFunctionOneParamResult;
  1324. const
  1325. WIT_CONTENT = 'b:u8';
  1326. begin
  1327. InitParser(WrapFunc(WIT_CONTENT,'u32'));
  1328. ParseFunc('a',['b'],[wtU8],wtU32);
  1329. end;
  1330. procedure TTestWITParser.TestParseFunctionTwoParams;
  1331. const
  1332. WIT_CONTENT = 'b : u8, c : list<u8>';
  1333. begin
  1334. InitParser(WrapFunc(WIT_CONTENT));
  1335. ParseFunc('a',['b','c'],[wtU8, wtList],wtVoid);
  1336. end;
  1337. procedure TTestWITParser.TestParseFunctionTwoParamsResult;
  1338. const
  1339. WIT_CONTENT = 'b : u8, c : list<u8>';
  1340. begin
  1341. InitParser(WrapFunc(WIT_CONTENT,'result<_,u32>'));
  1342. ParseFunc('a',['b','c'],[wtU8, wtList],wtResult);
  1343. end;
  1344. procedure TTestWITParser.TestParseWorldEmpty;
  1345. const
  1346. WIT_CONTENT = 'world a {}';
  1347. begin
  1348. InitParser(WIT_CONTENT);
  1349. ParseWorld('a',0,0,0,0,0);
  1350. end;
  1351. procedure TTestWITParser.TestParseWorldUse;
  1352. const
  1353. WIT_CONTENT = 'world a { use b.{c}; }';
  1354. var
  1355. lWorld : TWITWorld;
  1356. lUse : TWITUse;
  1357. begin
  1358. InitParser(WIT_CONTENT);
  1359. lWorld:=ParseWorld('a',0,0,1,0,0);
  1360. lUse:=lWorld.UsesList[0];
  1361. AssertEquals('Export name','b',lUse.Path.Identifier);
  1362. end;
  1363. procedure TTestWITParser.TestParseWorldUseAnnotation;
  1364. const
  1365. WIT_CONTENT = 'world a { @since(version = 1.1.1) use b.{c}; }';
  1366. var
  1367. lWorld : TWITWorld;
  1368. lUse : TWITUse;
  1369. begin
  1370. InitParser(WIT_CONTENT);
  1371. lWorld:=ParseWorld('a',0,0,1,0,0);
  1372. lUse:=lWorld.UsesList[0];
  1373. AssertEquals('Export name','b',lUse.Path.Identifier);
  1374. AssertEquals('Have annotation',1,lUse.Annotations.Count);
  1375. AssertEquals('since annotation','since',lUse.Annotations[0].Name);
  1376. end;
  1377. procedure TTestWITParser.TestParseWorldExport;
  1378. const
  1379. WIT_CONTENT = 'world a { export b; }';
  1380. var
  1381. lWorld : TWITWorld;
  1382. lExport : TWITExchange;
  1383. begin
  1384. InitParser(WIT_CONTENT);
  1385. lWorld:=ParseWorld('a',1,0,0,0,0);
  1386. lExport:=lWorld.Exported[0];
  1387. AssertEquals('Export name','b',lExport.Name);
  1388. end;
  1389. procedure TTestWITParser.TestParseWorldExportUse;
  1390. const
  1391. WIT_CONTENT = 'world a { export b:c/[email protected]; }';
  1392. var
  1393. lWorld : TWITWorld;
  1394. lExport : TWITExchange;
  1395. begin
  1396. InitParser(WIT_CONTENT);
  1397. lWorld:=ParseWorld('a',1,0,0,0,0);
  1398. lExport:=lWorld.Exported[0];
  1399. AssertEquals('Export name','b:c/[email protected]',lExport.Name);
  1400. end;
  1401. procedure TTestWITParser.TestParseWorldExportFunction;
  1402. const
  1403. WIT_CONTENT = 'world a { export b:func (c:u32) ; }';
  1404. var
  1405. lWorld : TWITWorld;
  1406. lExport : TWITExchange;
  1407. lExportFunc : TWITExchangeFunc absolute lExport;
  1408. begin
  1409. InitParser(WIT_CONTENT);
  1410. lWorld:=ParseWorld('a',1,0,0,0,0);
  1411. lExport:=lWorld.Exported[0];
  1412. AssertEquals('Export name','b',lExport.Name);
  1413. AssertEquals('export class',TWITExchangeFunc,lExport.ClassType);
  1414. AssertNotNull('export typedef',lExportFunc.TypeDef);
  1415. end;
  1416. procedure TTestWITParser.TestParseWorldExportInterface;
  1417. const
  1418. WIT_CONTENT = 'world a { export b:interface { c: func (d:u32) ; } }';
  1419. var
  1420. lWorld : TWITWorld;
  1421. lExport : TWITExchange;
  1422. lExportIntf : TWITExchangeInterface absolute lExport;
  1423. begin
  1424. InitParser(WIT_CONTENT);
  1425. lWorld:=ParseWorld('a',1,0,0,0,0);
  1426. lExport:=lWorld.Exported[0];
  1427. AssertEquals('Export name','b',lExport.Name);
  1428. AssertEquals('export class',TWITExchangeInterface,lExport.ClassType);
  1429. AssertInterface('counts',lExportIntf.TypeDef,'b',1,0,0)
  1430. end;
  1431. procedure TTestWITParser.TestParseWorldImport;
  1432. const
  1433. WIT_CONTENT = 'world a { import b; }';
  1434. var
  1435. lWorld : TWITWorld;
  1436. lExport : TWITExchange;
  1437. begin
  1438. InitParser(WIT_CONTENT);
  1439. lWorld:=ParseWorld('a',0,1,0,0,0);
  1440. lExport:=lWorld.Imported[0];
  1441. AssertEquals('Import name','b',lExport.Name);
  1442. end;
  1443. procedure TTestWITParser.TestParseWorldImportUse;
  1444. const
  1445. WIT_CONTENT = 'world a { import b:c/[email protected]; }';
  1446. var
  1447. lWorld : TWITWorld;
  1448. lExport : TWITExchange;
  1449. begin
  1450. InitParser(WIT_CONTENT);
  1451. lWorld:=ParseWorld('a',0,1,0,0,0);
  1452. lExport:=lWorld.Imported[0];
  1453. AssertEquals('Export name','b:c/[email protected]',lExport.Name);
  1454. end;
  1455. procedure TTestWITParser.TestParseWorldImportFunction;
  1456. const
  1457. WIT_CONTENT = 'world a { import b:func (c:u32) ; }';
  1458. var
  1459. lWorld : TWITWorld;
  1460. lExport : TWITExchange;
  1461. lExportFunc : TWITExchangeFunc absolute lExport;
  1462. begin
  1463. InitParser(WIT_CONTENT);
  1464. lWorld:=ParseWorld('a',0,1,0,0,0);
  1465. lExport:=lWorld.Imported[0];
  1466. AssertEquals('Export name','b',lExport.Name);
  1467. AssertEquals('export class',TWITExchangeFunc,lExport.ClassType);
  1468. AssertNotNull('export typedef',lExportFunc.TypeDef);
  1469. end;
  1470. procedure TTestWITParser.TestParseWorldImportInterface;
  1471. const
  1472. WIT_CONTENT = 'world a { import b:interface { c: func (d:u32) ; } }';
  1473. var
  1474. lWorld : TWITWorld;
  1475. lExport : TWITExchange;
  1476. lExportIntf : TWITExchangeInterface absolute lExport;
  1477. begin
  1478. InitParser(WIT_CONTENT);
  1479. lWorld:=ParseWorld('a',0,1,0,0,0);
  1480. lExport:=lWorld.Imported[0];
  1481. AssertEquals('Export name','b',lExport.Name);
  1482. AssertEquals('export class',TWITExchangeInterface,lExport.ClassType);
  1483. AssertInterface('counts',lExportIntf.TypeDef,'b',1,0,0)
  1484. end;
  1485. procedure TTestWITParser.TestParseWorldInclude;
  1486. const
  1487. WIT_CONTENT = 'world a { include b; }';
  1488. var
  1489. lWorld : TWITWorld;
  1490. lInclude : TWITInclude;
  1491. begin
  1492. InitParser(WIT_CONTENT);
  1493. lWorld:=ParseWorld('a',0,0,0,0,1);
  1494. lInclude:=lWorld.Includes[0];
  1495. AssertInclude('First',lInclude,'b',[],[]);
  1496. end;
  1497. procedure TTestWITParser.TestParseWorldIncludeUse;
  1498. const
  1499. WIT_CONTENT = 'world a { include b:c/d; }';
  1500. var
  1501. lWorld : TWITWorld;
  1502. lInclude : TWITInclude;
  1503. begin
  1504. InitParser(WIT_CONTENT);
  1505. lWorld:=ParseWorld('a',0,0,0,0,1);
  1506. lInclude:=lWorld.Includes[0];
  1507. AssertInclude('First',lInclude,'b:c/d',[],[]);
  1508. end;
  1509. procedure TTestWITParser.TestParseWorldIncludeUseList;
  1510. const
  1511. WIT_CONTENT = 'world a { include b:c/d with { e as f } }';
  1512. var
  1513. lWorld : TWITWorld;
  1514. lInclude : TWITInclude;
  1515. begin
  1516. InitParser(WIT_CONTENT);
  1517. lWorld:=ParseWorld('a',0,0,0,0,1);
  1518. lInclude:=lWorld.Includes[0];
  1519. AssertInclude('First',lInclude,'b:c/d',['e'],['f']);
  1520. end;
  1521. procedure TTestWITParser.TestParseWorldIncludeUseList2;
  1522. const
  1523. WIT_CONTENT = 'world a { include b:c/d with { e as f, g as h } }';
  1524. var
  1525. lWorld : TWITWorld;
  1526. lInclude : TWITInclude;
  1527. begin
  1528. InitParser(WIT_CONTENT);
  1529. lWorld:=ParseWorld('a',0,0,0,0,1);
  1530. lInclude:=lWorld.Includes[0];
  1531. AssertInclude('First',lInclude,'b:c/d',['e','g'],['f','h']);
  1532. end;
  1533. procedure TTestWITParser.TestParseWorldTypeDef;
  1534. const
  1535. WIT_CONTENT = 'world a { type x = u32; }';
  1536. var
  1537. lWorld : TWITWorld;
  1538. lType : TWITTypeDef;
  1539. begin
  1540. InitParser(WIT_CONTENT);
  1541. lWorld:=ParseWorld('a',0,0,0,1,0);
  1542. lType:=lWorld.TypeDefs[0];
  1543. AssertTypeDef('type',lType,'x',wtU32);
  1544. end;
  1545. procedure TTestWITParser.TestParseWorldEnumType;
  1546. const
  1547. WIT_CONTENT = 'world a { enum x {y,z} }';
  1548. var
  1549. lWorld : TWITWorld;
  1550. lType : TWITTypeDef;
  1551. begin
  1552. InitParser(WIT_CONTENT);
  1553. lWorld:=ParseWorld('a',0,0,0,1,0);
  1554. lType:=lWorld.TypeDefs[0];
  1555. AssertEnumType('type',lType,'x',['y','z']);
  1556. end;
  1557. procedure TTestWITParser.TestParseWorldVariantType;
  1558. const
  1559. WIT_CONTENT = 'world a { variant x { y, z} }';
  1560. var
  1561. lWorld : TWITWorld;
  1562. lType : TWITTypeDef;
  1563. begin
  1564. InitParser(WIT_CONTENT);
  1565. lWorld:=ParseWorld('a',0,0,0,1,0);
  1566. lType:=lWorld.TypeDefs[0];
  1567. AssertVariantType('type',lType,'x',['y','z']);
  1568. end;
  1569. procedure TTestWITParser.TestParseWorldRecordType;
  1570. const
  1571. WIT_CONTENT = 'world a { record x { y: u32, z: u8} }';
  1572. var
  1573. lWorld : TWITWorld;
  1574. lType : TWITTypeDef;
  1575. begin
  1576. InitParser(WIT_CONTENT);
  1577. lWorld:=ParseWorld('a',0,0,0,1,0);
  1578. lType:=lWorld.TypeDefs[0];
  1579. AssertRecordType('type',lType,'x',['y','z'],[wtu32,wtu8]);
  1580. end;
  1581. procedure TTestWITParser.TestParseWorldFlagsType;
  1582. const
  1583. WIT_CONTENT = 'world a { flags x { y, z} }';
  1584. var
  1585. lWorld : TWITWorld;
  1586. lType : TWITTypeDef;
  1587. begin
  1588. InitParser(WIT_CONTENT);
  1589. lWorld:=ParseWorld('a',0,0,0,1,0);
  1590. lType:=lWorld.TypeDefs[0];
  1591. AssertFlagsType('type',lType,'x',['y','z']);
  1592. end;
  1593. procedure TTestWITParser.TestParseInterfaceUse;
  1594. const
  1595. WIT_CONTENT = 'interface a { use b.{c}; }';
  1596. begin
  1597. InitParser(WIT_CONTENT);
  1598. FDocument := FParser.ParseDocument;
  1599. AssertNotNull('Have package', FDocument.DefaultPackage);
  1600. AssertEquals('Interface count.', 1, FDocument.Interfaces.Count);
  1601. AssertEquals('Use count.', 1, FDocument.Interfaces[0].UseList.Count);
  1602. end;
  1603. procedure TTestWITParser.TestParseInterfaceUseGate;
  1604. const
  1605. WIT_CONTENT = 'interface a { @since (version = 1.1.1) use b.{c}; }';
  1606. begin
  1607. InitParser(WIT_CONTENT);
  1608. FDocument := FParser.ParseDocument;
  1609. AssertNotNull('Have package', FDocument.DefaultPackage);
  1610. AssertEquals('Interface count.', 1, FDocument.Interfaces.Count);
  1611. AssertEquals('Use count.', 1, FDocument.Interfaces[0].UseList.Count);
  1612. AssertEquals('Use annotation count.', 1, FDocument.Interfaces[0].UseList[0].Annotations.Count);
  1613. end;
  1614. procedure TTestWITParser.TestParsePackageEmpty;
  1615. const
  1616. WIT_CONTENT = 'package foo:empty;';
  1617. var
  1618. LPackage: TWITPackage;
  1619. begin
  1620. InitParser(WIT_CONTENT);
  1621. FDocument := FParser.ParseDocument;
  1622. AssertNotNull('Have package', FDocument.DefaultPackage);
  1623. AssertEquals('Interface count.', 0, FDocument.Interfaces.Count);
  1624. AssertEquals('World count.', 0, FDocument.Worlds.Count);
  1625. LPackage := FDocument.DefaultPackage;
  1626. AssertPackage('Parsed package "foo:empty"', LPackage,
  1627. 'foo', 'empty', '', 0, 0, 0, 0, 0);
  1628. end;
  1629. procedure TTestWITParser.TestParsePackageVersions;
  1630. const
  1631. ScenarioCount = 9;
  1632. Scenarios : array [1..ScenarioCount] of string = (
  1633. 'package a:[email protected] {}',
  1634. 'package a:[email protected] {}',
  1635. 'package a:[email protected] {}',
  1636. 'package a:[email protected]+a {}',
  1637. 'package a:[email protected]+1 {}',
  1638. 'package a:[email protected]+1a {}',
  1639. 'package a:[email protected] {}',
  1640. 'package a:[email protected] {}',
  1641. 'package a:[email protected] {}'
  1642. );
  1643. var
  1644. I,p : Integer;
  1645. lScenario,
  1646. lVersion : string;
  1647. lMessage : String;
  1648. begin
  1649. For I:=1 to ScenarioCount do
  1650. begin
  1651. lScenario:=Scenarios[i];
  1652. P:=Pos('@',lScenario);
  1653. lVersion:=Copy(lScenario,P+1,pos('{',lScenario)-2-P);
  1654. lMessage:=Format('Scenario[%d] "%s": ',[i,lScenario]);
  1655. InitParser(lScenario);
  1656. try
  1657. FDocument:=FParser.ParseDocument;
  1658. except
  1659. on E : Exception do
  1660. Fail('Exception %s during scenario %s: "%s"',[E.ClassName,lMessage,E.Message]);
  1661. end;
  1662. AssertEquals('Have package ',1,FDocument.Packages.Count);
  1663. AssertPackage(lMessage,FDocument.Packages[0],'a','b',lVersion)
  1664. end;
  1665. end;
  1666. initialization
  1667. RegisterTest(TTestWITParser);
  1668. end.