tcstreaming.pp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. {$mode objfpc}
  2. {$h+}
  3. unit tcstreaming;
  4. interface
  5. Uses
  6. SysUtils,Classes, fpcunit, testutils, testregistry;
  7. Type
  8. { TTestStreaming }
  9. TTestStreaming = Class(TTestCase)
  10. Private
  11. FStream : TMemoryStream;
  12. Function ReadByte : byte;
  13. Function ReadWord : Word;
  14. Function ReadInteger : LongInt;
  15. Function ReadInt64 : Int64;
  16. function ReadBareStr: string;
  17. function ReadString(V : TValueType): string;
  18. function ReadWideString(V : TValueType): WideString;
  19. Procedure Fail(FMt : String; Args : Array of const); overload;
  20. Public
  21. Procedure Setup; override;
  22. Procedure TearDown; override;
  23. Procedure SaveToStream(C : TComponent);
  24. Function ReadValue : TValueType;
  25. Procedure ExpectValue(AValue : TValueType);
  26. Procedure ExpectFlags(Flags : TFilerFlags; APosition : Integer);
  27. Procedure ExpectInteger(AValue : Integer);
  28. Procedure ExpectByte(AValue : Byte);
  29. Procedure ExpectInt64(AValue : Int64);
  30. Procedure ExpectBareString(AValue : String);
  31. Procedure ExpectString(AValue : String);
  32. Procedure ExpectSingle(AValue : Single);
  33. Procedure ExpectExtended(AValue : Extended);
  34. Procedure ExpectCurrency(AValue : Currency);
  35. Procedure ExpectIdent(AValue : String);
  36. Procedure ExpectDate(AValue : TDateTime);
  37. Procedure ExpectWideString(AValue : WideString);
  38. Procedure ExpectEndofList;
  39. Procedure ExpectSignature;
  40. Procedure ExpectEndOfStream;
  41. end;
  42. implementation
  43. uses typinfo;
  44. Function ValName(V : TValueType) : String;
  45. begin
  46. Result:=GetEnumName(TypeInfo(TValueType),Ord(v));
  47. end;
  48. { TTestStreaming }
  49. procedure TTestStreaming.ExpectByte(AValue: Byte);
  50. Var
  51. B : Byte;
  52. begin
  53. B:=ReadByte;
  54. If (B<>AValue) then
  55. Fail('Expected byte %d, got %d',[AValue,B]);
  56. end;
  57. procedure TTestStreaming.ExpectCurrency(AValue: Currency);
  58. Var
  59. C : Currency;
  60. begin
  61. ExpectValue(vaCurrency);
  62. FStream.Read(C,Sizeof(C));
  63. If (C<>AValue) then
  64. Fail('Expected currency %f, got %f',[AValue,C]);
  65. end;
  66. procedure TTestStreaming.ExpectDate(AValue: TDateTime);
  67. Var
  68. C : TDateTime;
  69. begin
  70. ExpectValue(vaDate);
  71. FStream.Read(C,Sizeof(C));
  72. If (C<>AValue) then
  73. Fail('Expected datetime %f, got %f',[AValue,C]);
  74. end;
  75. procedure TTestStreaming.ExpectEndofList;
  76. begin
  77. ExpectValue(vaNull);
  78. end;
  79. procedure TTestStreaming.ExpectExtended(AValue: Extended);
  80. Var
  81. E : Extended;
  82. begin
  83. ExpectValue(vaExtended);
  84. FStream.Read(E,Sizeof(E));
  85. If Abs(E-AValue)>0.01 then
  86. Fail('Expected extended %f, got %f',[AValue,E]);
  87. end;
  88. procedure TTestStreaming.ExpectFlags(Flags: TFilerFlags;
  89. APosition: Integer);
  90. var
  91. Prefix: Byte;
  92. F : TFilerFlags;
  93. B : Byte;
  94. I : Integer;
  95. begin
  96. F := [];
  97. I:=0;
  98. B:=ReadByte;
  99. if B and $F0 = $F0 then
  100. begin
  101. Integer(F) := B and $0F;
  102. if ffChildPos in Flags then
  103. I:=ReadInteger;
  104. end
  105. else
  106. FStream.Position:=FStream.Position-1;
  107. If (FLags<>F) then
  108. Fail('Wrong Flags, expected %d, got %d',[Integer(Flags),B]);
  109. If I<>APosition then
  110. Fail('Wrong position, expected %d, got %d',[APosition,I]);
  111. end;
  112. procedure TTestStreaming.ExpectIdent(AValue: String);
  113. var
  114. L : Byte;
  115. V : TValueType;
  116. S : String;
  117. begin
  118. V:=ReadValue;
  119. case V of
  120. vaIdent:
  121. begin
  122. L:=ReadByte;
  123. SetLength(S,L);
  124. FStream.Read(S[1], L);
  125. end;
  126. vaFalse:
  127. S := 'False';
  128. vaTrue:
  129. S := 'True';
  130. vaNil:
  131. S := 'nil';
  132. vaNull:
  133. S := 'Null';
  134. else
  135. Fail('Expected identifier property type, got %s',[valName(V)]);
  136. end;
  137. If (S<>AValue) then
  138. Fail('Wrong identifier %s, expected %s',[S,AValue]);
  139. end;
  140. procedure TTestStreaming.ExpectInt64(AValue: Int64);
  141. Var
  142. V : TValueType;
  143. I : Int64;
  144. begin
  145. V:=ReadValue;
  146. Case V of
  147. vaInt8 : I:=ReadByte;
  148. vaInt16 : I:=ReadWord;
  149. vaInt32 : I:=ReadInteger;
  150. vaInt64 : I:=ReadInt64;
  151. else
  152. Fail('Expected integer property type, got %s',[valName(V)]);
  153. end;
  154. If (AValue<>I) then
  155. Fail('Expected integer %d, but got %d',[AValue,I]);
  156. end;
  157. procedure TTestStreaming.ExpectInteger(AValue: Integer);
  158. Var
  159. V : TValueType;
  160. I : Integer;
  161. begin
  162. V:=ReadValue;
  163. Case V of
  164. vaInt8 : I:=ReadByte;
  165. vaInt16 : I:=ReadWord;
  166. vaInt32 : I:=ReadInteger;
  167. else
  168. Fail('Expected integer property type, got %s',[valName(V)]);
  169. end;
  170. If (AValue<>I) then
  171. Fail('Expected integer %d, but got %d',[AValue,I]);
  172. end;
  173. procedure TTestStreaming.ExpectSignature;
  174. const
  175. Sig : array[1..4] of Char = 'TPF0';
  176. var
  177. E,L : Longint;
  178. begin
  179. L:=ReadInteger;
  180. E:=Longint(Sig);
  181. if L<>E then
  182. Fail('Invalid signature %d, expected %d',[L,E]);
  183. end;
  184. procedure TTestStreaming.ExpectSingle(AValue: Single);
  185. Var
  186. S : Single;
  187. begin
  188. ExpectValue(vaSingle);
  189. FStream.Read(S,SizeOf(Single));
  190. If Abs(AValue-S)>0.0001 then
  191. Fail('Expected single %f, but got %s',[AValue,S]);
  192. end;
  193. function TTestStreaming.ReadString(V : TValueType): string;
  194. var
  195. L: Integer;
  196. B : Byte;
  197. begin
  198. If V in [vaWString, vaUTF8String] then
  199. Result := ReadWideString(V)
  200. else
  201. begin
  202. L := 0;
  203. case V of
  204. vaString:
  205. begin
  206. FStream.Read(B, SizeOf(B));
  207. L:=B;
  208. end;
  209. vaLString:
  210. FStream.Read(L, SizeOf(Integer));
  211. else
  212. Fail('Wrong type %s, expected string type.',[ValName(V)]);
  213. end;
  214. SetLength(Result, L);
  215. If (L>0) then
  216. FStream.Read(PByte(Result)^, L);
  217. end;
  218. end;
  219. function TTestStreaming.ReadWideString(V : TValueType): WideString;
  220. var
  221. L: Integer;
  222. Temp: String;
  223. begin
  224. if V in [vaString, vaLString] then
  225. Result := ReadString(V)
  226. else
  227. begin
  228. L := 0;
  229. case V of
  230. vaWString:
  231. begin
  232. FStream.Read(L, SizeOf(Integer));
  233. SetLength(Result, L);
  234. FStream.Read(Pointer(Result)^, L * 2);
  235. end;
  236. vaUTF8String:
  237. begin
  238. FStream.Read(L, SizeOf(Integer));
  239. SetLength(Temp, L);
  240. FStream.Read(Pointer(Temp)^, L);
  241. Result:=Temp
  242. end;
  243. else
  244. Fail('Wrong type %s, expected widestring type.',[ValName(V)]);
  245. end;
  246. end;
  247. end;
  248. procedure TTestStreaming.ExpectString(AValue: String);
  249. Var
  250. V : TValueType;
  251. S : String;
  252. begin
  253. V:=ReadValue;
  254. If v in [vaString,vaLstring,vaWString,vaUTF8String] then
  255. S:=ReadString(V)
  256. else
  257. Fail('Expected string type, but got : %s',[ValName(V)]);
  258. If (S<>AValue) then
  259. Fail('Expected string "%s", but got "%s"',[AVAlue,S]);
  260. end;
  261. procedure TTestStreaming.ExpectValue(AValue: TValueType);
  262. Var
  263. V : TValueType;
  264. begin
  265. V:=ReadValue;
  266. If (V<>AValue) then
  267. Fail('Expecting value %s, but read %s',[ValName(AValue),ValName(V)]);
  268. end;
  269. procedure TTestStreaming.ExpectWideString(AValue: WideString);
  270. Var
  271. W : WideString;
  272. V : TValueType;
  273. begin
  274. V:=ReadValue;
  275. If v in [vaString,vaLstring,vaWString,vaUTF8String] then
  276. W:=ReadWideString(V)
  277. else
  278. Fail('Expected string type, but got : %s',[ValName(V)]);
  279. If (W<>AValue) then
  280. Fail('Expected string "%s", but got "%s"',[AVAlue,W]);
  281. end;
  282. procedure TTestStreaming.Fail(Fmt: String; Args: array of const);
  283. begin
  284. Fail(Format(Fmt,Args));
  285. end;
  286. function TTestStreaming.ReadValue: TValueType;
  287. {$IFDEF FPC}
  288. var b : byte;
  289. {$ENDIF}
  290. begin
  291. {$IFDEF FPC}
  292. FStream.Read(b,1);
  293. result := TValueType(b);
  294. {$ELSE}
  295. FStream.Read(Result,SizeOf(Result));
  296. {$ENDIF}
  297. end;
  298. procedure TTestStreaming.Setup;
  299. begin
  300. FStream:=TMemoryStream.Create;
  301. end;
  302. procedure TTestStreaming.SaveToStream(C: TComponent);
  303. var
  304. s: TStream;
  305. begin
  306. C.Name:='Test'+C.ClassName;
  307. FStream.Clear;
  308. FStream.WriteComponent(C);
  309. FStream.Position:=0;
  310. // for debugging purposes, you can write a component to file too
  311. // set the class name of the component you want to write to disk in the next line
  312. if (C.ClassName='TStreamedOwnedComponentsX') then begin
  313. s := TFileStream.Create(C.ClassName+'.txt', fmCreate, fmShareDenyNone );
  314. s.WriteComponent(C);
  315. s.Free;
  316. end;
  317. end;
  318. procedure TTestStreaming.TearDown;
  319. begin
  320. FreeAndNil(FStream);
  321. end;
  322. function TTestStreaming.ReadByte: byte;
  323. begin
  324. FStream.Read(Result,SizeOf(Result));
  325. end;
  326. function TTestStreaming.ReadInt64: Int64;
  327. begin
  328. FStream.Read(Result,SizeOf(Result));
  329. end;
  330. function TTestStreaming.ReadInteger: LongInt;
  331. begin
  332. FStream.Read(Result,SizeOf(Result));
  333. end;
  334. function TTestStreaming.ReadWord: Word;
  335. begin
  336. FStream.Read(Result,SizeOf(Result));
  337. end;
  338. function TTestStreaming.ReadBareStr: string;
  339. var
  340. L: Byte;
  341. begin
  342. L:=ReadByte;
  343. SetLength(Result,L);
  344. Fstream.Read(Result[1], L);
  345. end;
  346. procedure TTestStreaming.ExpectBareString(AValue: String);
  347. Var
  348. S : String;
  349. begin
  350. S:=ReadBareStr;
  351. If (S<>AValue) then
  352. Fail('Expected bare string %s, got :%s',[AValue,S]);
  353. end;
  354. procedure TTestStreaming.ExpectEndOfStream;
  355. begin
  356. If (FStream.Position<>FStream.Size) then
  357. Fail('Expected at end of stream, current position=%d, size=%d',
  358. [FStream.Position,FStream.Size]);
  359. end;
  360. end.