tcstreaming.pp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. { Base class for component stream tests.
  2. Copyright (C) 2020 Michael Van Canneyt [email protected]
  3. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public
  4. License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version
  5. with the following modification:
  6. As a special exception, the copyright holders of this library give you permission to link this library with independent modules
  7. to produce an executable, regardless of the license terms of these independent modules,and to copy and distribute the resulting
  8. executable under terms of your choice, provided that you also meet, for each linked independent module, the terms and conditions
  9. of the license of that module. An independent module is a module which is not derived from or based on this library. If you
  10. modify this library, you may extend this exception to your version of the library, but you are not obligated to do so. If you do
  11. not wish to do so, delete this exception statement from your version.
  12. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details.
  14. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free
  15. Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA.
  16. }
  17. {$mode objfpc}
  18. {$h+}
  19. unit tcstreaming;
  20. interface
  21. Uses
  22. SysUtils,Classes, fpcunit, testregistry;
  23. Type
  24. { TTestStreaming }
  25. TTestStreaming = Class(TTestCase)
  26. Private
  27. FStream : TMemoryStream;
  28. FLastText : String;
  29. Function ReadByte : byte;
  30. Function ReadWord : Word;
  31. Function ReadInteger : LongInt;
  32. Function ReadNativeInt : NativeInt;
  33. function ReadBareStr: string;
  34. function ReadString(V : TValueType): string;
  35. function ReadWideString(V : TValueType): WideString;
  36. Procedure Fail(Fmt : String; Args : Array of const); overload;
  37. Public
  38. Procedure Setup; override;
  39. Procedure TearDown; override;
  40. Procedure ResetStream;
  41. Procedure SaveToStream(C : TComponent);
  42. Procedure LoadFromStream(C : TComponent);
  43. Procedure LoadFromTextStream(C : TComponent);
  44. Function ReadValue : TValueType;
  45. Procedure ExpectValue(AValue : TValueType);
  46. Procedure ExpectFlags(Flags : TFilerFlags; APosition : Integer);
  47. Procedure ExpectInteger(AValue : Integer);
  48. Procedure ExpectByte(AValue : Byte);
  49. Procedure ExpectInt64(AValue : NativeInt);
  50. Procedure ExpectBareString(AValue : String);
  51. Procedure ExpectString(AValue : String);
  52. Procedure ExpectSingle(AValue : Double);
  53. Procedure ExpectExtended(AValue : Extended);
  54. Procedure ExpectCurrency(AValue : Currency);
  55. Procedure ExpectIdent(AValue : String);
  56. Procedure ExpectDate(AValue : TDateTime);
  57. Procedure ExpectWideString(AValue : WideString);
  58. Procedure ExpectEndofList;
  59. Procedure ExpectSignature;
  60. Procedure ExpectEndOfStream;
  61. Procedure CheckAsString(const aData : String);
  62. Property LastText : String Read FLastText;
  63. end;
  64. implementation
  65. uses typinfo;
  66. Function ValName(V : TValueType) : String;
  67. begin
  68. Result:=GetEnumName(TypeInfo(TValueType),Ord(v));
  69. end;
  70. { TTestStreaming }
  71. procedure TTestStreaming.ExpectByte(AValue: Byte);
  72. Var
  73. B : Byte;
  74. begin
  75. B:=ReadByte;
  76. If (B<>AValue) then
  77. Fail('Expected byte %d, got %d',[AValue,B]);
  78. end;
  79. procedure TTestStreaming.ExpectCurrency(AValue: Currency);
  80. Var
  81. C : Double;
  82. begin
  83. ExpectValue(vaCurrency);
  84. FStream.ReadBufferData(C);
  85. If (C<>AValue) then
  86. Fail('Expected currency %f, got %f',[AValue,C]);
  87. end;
  88. procedure TTestStreaming.ExpectDate(AValue: TDateTime);
  89. Var
  90. C : TDateTime;
  91. begin
  92. ExpectValue(vaDate);
  93. FStream.ReadBufferData(C);
  94. If (C<>AValue) then
  95. Fail('Expected datetime %f, got %f',[AValue,C]);
  96. end;
  97. procedure TTestStreaming.ExpectEndofList;
  98. begin
  99. ExpectValue(vaNull);
  100. end;
  101. procedure TTestStreaming.ExpectExtended(AValue: Extended);
  102. Var
  103. E : Extended;
  104. begin
  105. ExpectValue(vaExtended);
  106. FStream.ReadBufferData(E);
  107. If Abs(E-AValue)>0.01 then
  108. Fail('Expected extended %f, got %f',[AValue,E]);
  109. end;
  110. procedure TTestStreaming.ExpectFlags(Flags: TFilerFlags;
  111. APosition: Integer);
  112. var
  113. FF : TFilerFlag;
  114. F : TFilerFlags;
  115. B : Byte;
  116. I : Integer;
  117. begin
  118. F := [];
  119. I:=0;
  120. B:=ReadByte;
  121. if (B and $F0) = $F0 then
  122. begin
  123. F:=[];
  124. for FF in TFilerFlag do
  125. if (B and (1 shl ord(FF)))<>0 then
  126. Include(F,FF);
  127. if ffChildPos in Flags then
  128. I:=ReadInteger;
  129. end
  130. else
  131. FStream.Position:=FStream.Position-1;
  132. If (FLags<>F) then
  133. Fail('Wrong Flags');
  134. If I<>APosition then
  135. Fail('Wrong position, expected %d, got %d',[APosition,I]);
  136. end;
  137. procedure TTestStreaming.ExpectIdent(AValue: String);
  138. var
  139. I,L : Byte;
  140. V : TValueType;
  141. S : String;
  142. C : Char;
  143. begin
  144. V:=ReadValue;
  145. case V of
  146. vaIdent:
  147. begin
  148. L:=ReadByte;
  149. SetLength(S,L);
  150. for I:=1 to L do
  151. begin
  152. FStream.ReadBufferData(C);
  153. S[i]:=C;
  154. end;
  155. end;
  156. vaFalse:
  157. S := 'False';
  158. vaTrue:
  159. S := 'True';
  160. vaNil:
  161. S := 'nil';
  162. vaNull:
  163. S := 'Null';
  164. else
  165. Fail(Format('Expected identifier property type, got %s',[valName(V)]));
  166. end;
  167. If (S<>AValue) then
  168. Fail(Format('Wrong identifier %s, expected %s',[S,AValue]));
  169. end;
  170. procedure TTestStreaming.ExpectInt64(AValue: NativeInt);
  171. Var
  172. V : TValueType;
  173. I : NativeInt;
  174. begin
  175. V:=ReadValue;
  176. Case V of
  177. vaInt8 : I:=ReadByte;
  178. vaInt16 : I:=ReadWord;
  179. vaInt32 : I:=ReadInteger;
  180. vaInt64 : I:=ReadNativeInt;
  181. else
  182. Fail(Format('Expected integer property type, got %s',[valName(V)]));
  183. end;
  184. If (AValue<>I) then
  185. Fail(Format('Expected integer %d, but got %d',[AValue,I]));
  186. end;
  187. procedure TTestStreaming.ExpectInteger(AValue: Integer);
  188. Var
  189. V : TValueType;
  190. I : Integer;
  191. begin
  192. V:=ReadValue;
  193. Case V of
  194. vaInt8 : I:=ReadByte;
  195. vaInt16 : I:=ReadWord;
  196. vaInt32 : I:=ReadInteger;
  197. else
  198. Fail('Expected integer property type, got %s',[valName(V)]);
  199. end;
  200. If (AValue<>I) then
  201. Fail('Expected integer %d, but got %d',[AValue,I]);
  202. end;
  203. procedure TTestStreaming.ExpectSignature;
  204. const
  205. // Sig : array[1..4] of Char = 'TPF0';
  206. // Integer version of 4 chars 'TPF0'
  207. FilerSignatureInt = 809914452;
  208. var
  209. E,L : Longint;
  210. begin
  211. L:=ReadInteger;
  212. E:=FilerSignatureInt;
  213. if L<>E then
  214. Fail('Invalid signature %d, expected %d',[L,E]);
  215. end;
  216. procedure TTestStreaming.ExpectSingle(AValue: Double);
  217. Var
  218. S : Double;
  219. begin
  220. ExpectValue(vaSingle);
  221. FStream.ReadBufferData(S);
  222. If Abs(AValue-S)>0.0001 then
  223. Fail('Expected single %f, but got %s',[AValue,S]);
  224. end;
  225. function TTestStreaming.ReadString(V : TValueType): string;
  226. var
  227. L,I : Integer;
  228. C : Char;
  229. begin
  230. // There is only 1 string type
  231. if V<>vaString then
  232. Fail('Wrong type %s, expected string type.',[ValName(V)]);
  233. L := 0;
  234. FStream.ReadBufferData(L);
  235. SetLength(Result, L);
  236. For I:=1 to L do
  237. begin
  238. FStream.ReadBufferData(C);
  239. Result[i]:=C;
  240. end;
  241. end;
  242. function TTestStreaming.ReadWideString(V : TValueType): WideString;
  243. begin
  244. Result := ReadString(V)
  245. end;
  246. procedure TTestStreaming.ExpectString(AValue: String);
  247. Var
  248. V : TValueType;
  249. S : String;
  250. begin
  251. V:=ReadValue;
  252. If v in [vaString,vaLstring,vaWString,vaUTF8String] then
  253. S:=ReadString(V)
  254. else
  255. Fail('Expected string type, but got : %s',[ValName(V)]);
  256. If (S<>AValue) then
  257. Fail('Expected string "%s", but got "%s"',[AVAlue,S]);
  258. end;
  259. procedure TTestStreaming.ExpectValue(AValue: TValueType);
  260. Var
  261. V : TValueType;
  262. begin
  263. V:=ReadValue;
  264. If (V<>AValue) then
  265. Fail('Expecting value %s, but read %s',[ValName(AValue),ValName(V)]);
  266. end;
  267. procedure TTestStreaming.ExpectWideString(AValue: WideString);
  268. Var
  269. W : WideString;
  270. V : TValueType;
  271. begin
  272. V:=ReadValue;
  273. If v in [vaString,vaLstring,vaWString,vaUTF8String] then
  274. W:=ReadWideString(V)
  275. else
  276. Fail('Expected string type, but got : %s',[ValName(V)]);
  277. If (W<>AValue) then
  278. Fail('Expected string "%s", but got "%s"',[AVAlue,W]);
  279. end;
  280. procedure TTestStreaming.Fail(Fmt: String; Args: array of Const);
  281. begin
  282. Fail(Format(Fmt,Args));
  283. end;
  284. function TTestStreaming.ReadValue: TValueType;
  285. var b : byte;
  286. begin
  287. FStream.ReadBufferData(b);
  288. result := TValueType(b);
  289. end;
  290. procedure TTestStreaming.Setup;
  291. begin
  292. FStream:=TMemoryStream.Create;
  293. end;
  294. procedure TTestStreaming.SaveToStream(C: TComponent);
  295. begin
  296. C.Name:='Test'+C.ClassName;
  297. FStream.Clear;
  298. FStream.WriteComponent(C);
  299. FStream.Position:=0;
  300. end;
  301. procedure TTestStreaming.LoadFromStream(C: TComponent);
  302. begin
  303. ResetStream;
  304. FStream.ReadComponent(C);
  305. end;
  306. procedure TTestStreaming.LoadFromTextStream(C: TComponent);
  307. Var
  308. BS : TBytesStream;
  309. SS : TStringStream;
  310. begin
  311. AssertTrue('Have text data',FLastText<>'');
  312. SS:=nil;
  313. SS:=TStringStream.Create(LastText);
  314. try
  315. BS:=TBytesStream.Create(Nil);
  316. ObjectTextToBinary(SS,BS);
  317. BS.Position:=0;
  318. BS.ReadComponent(C);
  319. finally
  320. SS.Free;
  321. BS.Free;
  322. end;
  323. end;
  324. procedure TTestStreaming.TearDown;
  325. begin
  326. FreeAndNil(FStream);
  327. end;
  328. procedure TTestStreaming.ResetStream;
  329. begin
  330. FStream.Position:=0;
  331. end;
  332. function TTestStreaming.ReadByte: byte;
  333. begin
  334. FStream.ReadBufferData(Result);
  335. end;
  336. function TTestStreaming.ReadNativeInt: NativeInt;
  337. begin
  338. FStream.ReadBufferData(Result);
  339. end;
  340. function TTestStreaming.ReadInteger: LongInt;
  341. begin
  342. FStream.ReadBufferData(Result);
  343. end;
  344. function TTestStreaming.ReadWord: Word;
  345. begin
  346. FStream.ReadBufferData(Result);
  347. end;
  348. function TTestStreaming.ReadBareStr: string;
  349. var
  350. L,I : Integer;
  351. C : Char;
  352. begin
  353. L:=ReadByte;
  354. SetLength(Result,L);
  355. for I:=1 to L do
  356. begin
  357. FStream.ReadBufferData(C);
  358. Result[I]:=C;
  359. end;
  360. end;
  361. procedure TTestStreaming.ExpectBareString(AValue: String);
  362. Var
  363. S : String;
  364. begin
  365. S:=ReadBareStr;
  366. If (S<>AValue) then
  367. Fail('Expected bare string %s, got :%s',[AValue,S]);
  368. end;
  369. procedure TTestStreaming.ExpectEndOfStream;
  370. begin
  371. If (FStream.Position<>FStream.Size) then
  372. Fail('Expected at end of stream, current position=%d, size=%d',
  373. [FStream.Position,FStream.Size]);
  374. end;
  375. procedure TTestStreaming.CheckAsString(const aData: String);
  376. Var
  377. SS : TStringStream;
  378. DS : String;
  379. begin
  380. FStream.Position:=0;
  381. SS:=TStringStream.Create('');
  382. try
  383. ObjectBinaryToText(FStream,SS);
  384. DS:=SS.Datastring;
  385. finally
  386. SS.Free;
  387. end;
  388. AssertEquals('Stream to string',aData,DS);
  389. FLastText:=DS;
  390. end;
  391. end.