blob: ec8d86db802a4b2da6c310122ab791af5a5b67f3 [file] [log] [blame]
Jens Geyered994552019-11-09 23:24:52 +01001unit TestSerializer.Tests;
2(*
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *)
20
21interface
22
23uses
24 Classes,
25 Windows,
26 SysUtils,
27 Generics.Collections,
28 Thrift,
29 Thrift.Exception,
30 Thrift.Socket,
31 Thrift.Transport,
32 Thrift.Protocol,
33 Thrift.Protocol.JSON,
34 Thrift.Protocol.Compact,
35 Thrift.Collections,
36 Thrift.Server,
37 Thrift.Utils,
38 Thrift.Serializer,
39 Thrift.Stream,
40 Thrift.WinHTTP,
41 Thrift.TypeRegistry,
42 System_,
43 DebugProtoTest,
44 TestSerializer.Data;
45
46
47type
48 TFactoryPair = record
49 prot : IProtocolFactory;
50 trans : ITransportFactory;
51 end;
52
53 TTestSerializer = class //extends TestCase {
54 private type
55 TMethod = (
56 mt_Bytes,
57 mt_Stream
58 );
59
60 private
61 FProtocols : TList< TFactoryPair>;
62 procedure AddFactoryCombination( const aProto : IProtocolFactory; const aTrans : ITransportFactory);
63 class function UserFriendlyName( const factory : TFactoryPair) : string; overload;
64 class function UserFriendlyName( const method : TMethod) : string; overload;
65
66 class function Serialize(const input : IBase; const factory : TFactoryPair) : TBytes; overload;
67 class procedure Serialize(const input : IBase; const factory : TFactoryPair; const aStream : TStream); overload;
68
69 class procedure Deserialize( const input : TBytes; const target : IBase; const factory : TFactoryPair); overload;
70 class procedure Deserialize( const input : TStream; const target : IBase; const factory : TFactoryPair); overload;
71
72 procedure Test_Serializer_Deserializer;
73 procedure Test_OneOfEach( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
74 procedure Test_CompactStruct( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
75
76 public
77 constructor Create;
78 destructor Destroy; override;
79
80 procedure RunTests;
81 end;
82
83
84implementation
85
86
87{ TTestSerializer }
88
89constructor TTestSerializer.Create;
90begin
91 inherited Create;
92 FProtocols := TList< TFactoryPair>.Create;
93
94 AddFactoryCombination( TBinaryProtocolImpl.TFactory.Create, nil);
95 AddFactoryCombination( TCompactProtocolImpl.TFactory.Create, nil);
96 AddFactoryCombination( TJSONProtocolImpl.TFactory.Create, nil);
97
98 AddFactoryCombination( TBinaryProtocolImpl.TFactory.Create, TFramedTransportImpl.TFactory.Create);
99 AddFactoryCombination( TCompactProtocolImpl.TFactory.Create, TFramedTransportImpl.TFactory.Create);
100 AddFactoryCombination( TJSONProtocolImpl.TFactory.Create, TFramedTransportImpl.TFactory.Create);
101
102 AddFactoryCombination( TBinaryProtocolImpl.TFactory.Create, TBufferedTransportImpl.TFactory.Create);
103 AddFactoryCombination( TCompactProtocolImpl.TFactory.Create, TBufferedTransportImpl.TFactory.Create);
104 AddFactoryCombination( TJSONProtocolImpl.TFactory.Create, TBufferedTransportImpl.TFactory.Create);
105end;
106
107
108destructor TTestSerializer.Destroy;
109begin
110 try
111 FreeAndNil( FProtocols);
112 finally
113 inherited Destroy;
114 end;
115end;
116
117
118procedure TTestSerializer.AddFactoryCombination( const aProto : IProtocolFactory; const aTrans : ITransportFactory);
119var rec : TFactoryPair;
120begin
121 rec.prot := aProto;
122 rec.trans := aTrans;
123 FProtocols.Add( rec);
124end;
125
126
127procedure TTestSerializer.Test_OneOfEach( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
128var tested, correct : IOneOfEach;
129 bytes : TBytes;
130 i : Integer;
131begin
132 // write
133 tested := Fixtures.CreateOneOfEach;
134 case method of
135 mt_Bytes: bytes := Serialize( tested, factory);
136 mt_Stream: begin
137 stream.Size := 0;
138 Serialize( tested, factory, stream);
139 end
140 else
141 ASSERT( FALSE);
142 end;
143
144 // init + read
145 tested := TOneOfEachImpl.Create;
146 case method of
147 mt_Bytes: Deserialize( bytes, tested, factory);
148 mt_Stream: begin
149 stream.Position := 0;
150 Deserialize( stream, tested, factory);
151 end
152 else
153 ASSERT( FALSE);
154 end;
155
156 // check
157 correct := Fixtures.CreateOneOfEach;
158 ASSERT( tested.Im_true = correct.Im_true);
159 ASSERT( tested.Im_false = correct.Im_false);
160 ASSERT( tested.A_bite = correct.A_bite);
161 ASSERT( tested.Integer16 = correct.Integer16);
162 ASSERT( tested.Integer32 = correct.Integer32);
163 ASSERT( tested.Integer64 = correct.Integer64);
164 ASSERT( Abs( tested.Double_precision - correct.Double_precision) < 1E-12);
165 ASSERT( tested.Some_characters = correct.Some_characters);
166 ASSERT( tested.Zomg_unicode = correct.Zomg_unicode);
167 ASSERT( tested.What_who = correct.What_who);
168
169 ASSERT( Length(tested.Base64) = Length(correct.Base64));
170 ASSERT( CompareMem( @tested.Base64[0], @correct.Base64[0], Length(correct.Base64)));
171
172 ASSERT( tested.Byte_list.Count = correct.Byte_list.Count);
173 for i := 0 to tested.Byte_list.Count-1
174 do ASSERT( tested.Byte_list[i] = correct.Byte_list[i]);
175
176 ASSERT( tested.I16_list.Count = correct.I16_list.Count);
177 for i := 0 to tested.I16_list.Count-1
178 do ASSERT( tested.I16_list[i] = correct.I16_list[i]);
179
180 ASSERT( tested.I64_list.Count = correct.I64_list.Count);
181 for i := 0 to tested.I64_list.Count-1
182 do ASSERT( tested.I64_list[i] = correct.I64_list[i]);
183end;
184
185
186procedure TTestSerializer.Test_CompactStruct( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
187var tested, correct : ICompactProtoTestStruct;
188 bytes : TBytes;
189begin
190 // write
191 tested := Fixtures.CreateCompactProtoTestStruct;
192 case method of
193 mt_Bytes: bytes := Serialize( tested, factory);
194 mt_Stream: begin
195 stream.Size := 0;
196 Serialize( tested, factory, stream);
197 end
198 else
199 ASSERT( FALSE);
200 end;
201
202 // init + read
203 correct := TCompactProtoTestStructImpl.Create;
204 case method of
205 mt_Bytes: Deserialize( bytes, tested, factory);
206 mt_Stream: begin
207 stream.Position := 0;
208 Deserialize( stream, tested, factory);
209 end
210 else
211 ASSERT( FALSE);
212 end;
213
214 // check
215 correct := Fixtures.CreateCompactProtoTestStruct;
216 ASSERT( correct.Field500 = tested.Field500);
217 ASSERT( correct.Field5000 = tested.Field5000);
218 ASSERT( correct.Field20000 = tested.Field20000);
219end;
220
221
222procedure TTestSerializer.Test_Serializer_Deserializer;
223var factory : TFactoryPair;
224 stream : TFileStream;
225 method : TMethod;
226begin
227 stream := TFileStream.Create( 'TestSerializer.dat', fmCreate);
228 try
229 for method in [Low(TMethod)..High(TMethod)] do begin
230 Writeln( UserFriendlyName(method));
231
232 for factory in FProtocols do begin
233 Writeln('- '+UserFriendlyName(factory));
234
235 Test_OneOfEach( method, factory, stream);
236 Test_CompactStruct( method, factory, stream);
237 end;
238
239 Writeln;
240 end;
241
242 finally
243 stream.Free;
244 end;
245end;
246
247
248class function TTestSerializer.UserFriendlyName( const factory : TFactoryPair) : string;
249begin
250 result := Copy( (factory.prot as TObject).ClassName, 2, MAXINT);
251
252 if factory.trans <> nil
253 then result := Copy( (factory.trans as TObject).ClassName, 2, MAXINT) +' '+ result;
254
255 result := StringReplace( result, 'Impl', '', [rfReplaceAll]);
256 result := StringReplace( result, 'Transport.TFactory', '', [rfReplaceAll]);
257 result := StringReplace( result, 'Protocol.TFactory', '', [rfReplaceAll]);
258end;
259
260
261class function TTestSerializer.UserFriendlyName( const method : TMethod) : string;
262begin
263 result := EnumUtils<TMethod>.ToString(Ord(method));
264 result := StringReplace( result, 'mt_', '', [rfReplaceAll]);
265end;
266
267
268procedure TTestSerializer.RunTests;
269begin
270 try
271 Test_Serializer_Deserializer;
272 except
273 on e:Exception do begin
274 Writeln( e.ClassName+': '+ e.Message);
275 Write('Hit ENTER to close ... '); Readln;
276 end;
277 end;
278end;
279
280
281class function TTestSerializer.Serialize(const input : IBase; const factory : TFactoryPair) : TBytes;
282var serial : TSerializer;
283begin
284 serial := TSerializer.Create( factory.prot, factory.trans);
285 try
286 result := serial.Serialize( input);
287 finally
288 serial.Free;
289 end;
290end;
291
292
293class procedure TTestSerializer.Serialize(const input : IBase; const factory : TFactoryPair; const aStream : TStream);
294var serial : TSerializer;
295begin
296 serial := TSerializer.Create( factory.prot, factory.trans);
297 try
298 serial.Serialize( input, aStream);
299 finally
300 serial.Free;
301 end;
302end;
303
304
305class procedure TTestSerializer.Deserialize( const input : TBytes; const target : IBase; const factory : TFactoryPair);
306var serial : TDeserializer;
307begin
308 serial := TDeserializer.Create( factory.prot, factory.trans);
309 try
310 serial.Deserialize( input, target);
311 finally
312 serial.Free;
313 end;
314end;
315
316
317class procedure TTestSerializer.Deserialize( const input : TStream; const target : IBase; const factory : TFactoryPair);
318var serial : TDeserializer;
319begin
320 serial := TDeserializer.Create( factory.prot, factory.trans);
321 try
322 serial.Deserialize( input, target);
323 finally
324 serial.Free;
325 end;
326end;
327
328
329end.