blob: 9ca90d900f03268690b77306ca3b28c3b24b57a6 [file] [log] [blame]
Jake Farrell7ae13e12011-10-18 14:35:26 +00001(*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *)
19
20unit TestClient;
21
22interface
23
24uses
Jake Farrell27274222011-11-10 20:32:44 +000025 Windows, SysUtils, Classes,
26 DateUtils,
27 Generics.Collections,
28 TestConstants,
Jake Farrelle34009b2011-11-17 00:17:29 +000029 Thrift,
Jake Farrell27274222011-11-10 20:32:44 +000030 Thrift.Protocol.JSON,
31 Thrift.Protocol,
32 Thrift.Transport,
33 Thrift.Stream,
34 Thrift.Test,
35 Thrift.Collections,
36 Thrift.Console;
Jake Farrell7ae13e12011-10-18 14:35:26 +000037
38type
Jake Farrell7ae13e12011-10-18 14:35:26 +000039 TThreadConsole = class
40 private
41 FThread : TThread;
42 public
43 procedure Write( const S : string);
44 procedure WriteLine( const S : string);
45 constructor Create( AThread: TThread);
46 end;
47
48 TClientThread = class( TThread )
49 private
50 FTransport : ITransport;
Jake Farrell27274222011-11-10 20:32:44 +000051 FProtocol : IProtocol;
Jake Farrell7ae13e12011-10-18 14:35:26 +000052 FNumIteration : Integer;
53 FConsole : TThreadConsole;
54
Jake Farrelle34009b2011-11-17 00:17:29 +000055 // test reporting, will be refactored out into separate class later
56 FTestGroup : string;
57 FSuccesses : Integer;
58 FErrors : TStringList;
59 procedure StartTestGroup( const aGroup : string);
Jake Farrell27274222011-11-10 20:32:44 +000060 procedure Expect( aTestResult : Boolean; const aTestInfo : string);
Jake Farrelle34009b2011-11-17 00:17:29 +000061 procedure ReportResults;
Jake Farrell27274222011-11-10 20:32:44 +000062
Jake Farrell7ae13e12011-10-18 14:35:26 +000063 procedure ClientTest;
Jake Farrell27274222011-11-10 20:32:44 +000064 procedure JSONProtocolReadWriteTest;
Jake Farrell7ae13e12011-10-18 14:35:26 +000065 protected
66 procedure Execute; override;
67 public
Jake Farrell27274222011-11-10 20:32:44 +000068 constructor Create(ATransport: ITransport; AProtocol : IProtocol; ANumIteration: Integer);
Jake Farrell7ae13e12011-10-18 14:35:26 +000069 destructor Destroy; override;
70 end;
71
72 TTestClient = class
73 private
74 class var
75 FNumIteration : Integer;
76 FNumThread : Integer;
77 public
78 class procedure Execute( const args: array of string);
79 end;
80
81implementation
82
Jake Farrelle34009b2011-11-17 00:17:29 +000083function BoolToString( b : Boolean) : string;
84// overrides global BoolToString()
85begin
86 if b
87 then result := 'true'
88 else result := 'false';
89end;
90
Jake Farrell27274222011-11-10 20:32:44 +000091
Jake Farrell7ae13e12011-10-18 14:35:26 +000092{ TTestClient }
93
94class procedure TTestClient.Execute(const args: array of string);
95var
96 i : Integer;
97 host : string;
98 port : Integer;
99 url : string;
100 bBuffered : Boolean;
101 bFramed : Boolean;
102 s : string;
103 n : Integer;
104 threads : array of TThread;
105 dtStart : TDateTime;
106 test : Integer;
107 thread : TThread;
108 trans : ITransport;
Jake Farrell27274222011-11-10 20:32:44 +0000109 prot : IProtocol;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000110 streamtrans : IStreamTransport;
111 http : IHTTPClient;
Jake Farrell27274222011-11-10 20:32:44 +0000112 protType, p : TKnownProtocol;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000113begin
114 bBuffered := False;;
115 bFramed := False;
Jake Farrell27274222011-11-10 20:32:44 +0000116 protType := prot_Binary;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000117 try
118 host := 'localhost';
119 port := 9090;
120 url := '';
121 i := 0;
122 try
123 while ( i < Length(args) ) do
124 begin
125 try
126 if ( args[i] = '-h') then
127 begin
128 Inc( i );
129 s := args[i];
130 n := Pos( ':', s);
131 if ( n > 0 ) then
132 begin
133 host := Copy( s, 1, n - 1);
134 port := StrToInt( Copy( s, n + 1, MaxInt));
135 end else
136 begin
137 host := s;
138 end;
139 end else
140 if (args[i] = '-u') then
141 begin
142 Inc( i );
143 url := args[i];
144 end else
145 if (args[i] = '-n') then
146 begin
147 Inc( i );
148 FNumIteration := StrToInt( args[i] );
149 end else
150 if (args[i] = '-b') then
151 begin
152 bBuffered := True;
153 Console.WriteLine('Using buffered transport');
154 end else
155 if (args[i] = '-f' ) or ( args[i] = '-framed') then
156 begin
157 bFramed := True;
158 Console.WriteLine('Using framed transport');
159 end else
160 if (args[i] = '-t') then
161 begin
162 Inc( i );
163 FNumThread := StrToInt( args[i] );
Jake Farrell27274222011-11-10 20:32:44 +0000164 end else
165 if (args[i] = '-prot') then // -prot JSON|binary
166 begin
167 Inc( i );
168 s := args[i];
169 for p:= Low(TKnownProtocol) to High(TKnownProtocol) do begin
170 if SameText( s, KNOWN_PROTOCOLS[p]) then begin
171 protType := p;
172 Console.WriteLine('Using '+KNOWN_PROTOCOLS[protType]+' protocol');
173 Break;
174 end;
175 end;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000176 end;
177 finally
178 Inc( i );
179 end;
180 end;
181 except
182 on E: Exception do
183 begin
184 Console.WriteLine( E.Message );
185 end;
186 end;
187
188 SetLength( threads, FNumThread);
189 dtStart := Now;
190
191 for test := 0 to FNumThread - 1 do
192 begin
193 if url = '' then
194 begin
195 streamtrans := TSocketImpl.Create( host, port );
196 trans := streamtrans;
197 if bBuffered then
198 begin
199 trans := TBufferedTransportImpl.Create( streamtrans );
200 end;
201
202 if bFramed then
203 begin
204 trans := TFramedTransportImpl.Create( trans );
205 end;
206 end else
207 begin
208 http := THTTPClientImpl.Create( url );
209 trans := http;
210 end;
Jake Farrell27274222011-11-10 20:32:44 +0000211
212 // create protocol instance, default to BinaryProtocol
213 case protType of
214 prot_Binary: prot := TBinaryProtocolImpl.Create( trans);
215 prot_JSON : prot := TJSONProtocolImpl.Create( trans);
216 else
217 ASSERT( FALSE); // unhandled case!
218 prot := TBinaryProtocolImpl.Create( trans); // use default
219 end;
220
221 thread := TClientThread.Create( trans, prot, FNumIteration);
Jake Farrell7ae13e12011-10-18 14:35:26 +0000222 threads[test] := thread;
223{$WARN SYMBOL_DEPRECATED OFF}
224 thread.Resume;
225{$WARN SYMBOL_DEPRECATED ON}
226 end;
227
228 for test := 0 to FNumThread - 1 do
229 begin
230 threads[test].WaitFor;
231 end;
232
233 for test := 0 to FNumThread - 1 do
234 begin
235 threads[test].Free;
236 end;
237
238 Console.Write('Total time: ' + IntToStr( MilliSecondsBetween(Now, dtStart)));
239
240 except
241 on E: Exception do
242 begin
243 Console.WriteLine( E.Message + ' ST: ' + E.StackTrace );
244 end;
245 end;
246
247 Console.WriteLine('');
248 Console.WriteLine('done!');
249end;
250
251{ TClientThread }
252
253procedure TClientThread.ClientTest;
254var
Jake Farrell7ae13e12011-10-18 14:35:26 +0000255 client : TThriftTest.Iface;
256 s : string;
257 i8 : ShortInt;
258 i32 : Integer;
259 i64 : Int64;
260 dub : Double;
261 o : IXtruct;
262 o2 : IXtruct2;
263 i : IXtruct;
264 i2 : IXtruct2;
265 mapout : IThriftDictionary<Integer,Integer>;
266 mapin : IThriftDictionary<Integer,Integer>;
267 j : Integer;
268 first : Boolean;
269 key : Integer;
270 listout : IThriftList<Integer>;
271 listin : IThriftList<Integer>;
272 setout : IHashSet<Integer>;
273 setin : IHashSet<Integer>;
274 ret : TNumberz;
275 uid : Int64;
276 mm : IThriftDictionary<Integer, IThriftDictionary<Integer, Integer>>;
Jake Farrelle34009b2011-11-17 00:17:29 +0000277 pos : IThriftDictionary<Integer, Integer>;
278 neg : IThriftDictionary<Integer, Integer>;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000279 m2 : IThriftDictionary<Integer, Integer>;
280 k2 : Integer;
281 insane : IInsanity;
282 truck : IXtruct;
283 whoa : IThriftDictionary<Int64, IThriftDictionary<TNumberz, IInsanity>>;
284 key64 : Int64;
285 val : IThriftDictionary<TNumberz, IInsanity>;
286 k2_2 : TNumberz;
287 k3 : TNumberz;
288 v2 : IInsanity;
Jake Farrell27274222011-11-10 20:32:44 +0000289 userMap : IThriftDictionary<TNumberz, Int64>;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000290 xtructs : IThriftList<IXtruct>;
291 x : IXtruct;
292 arg0 : ShortInt;
293 arg1 : Integer;
294 arg2 : Int64;
Jake Farrelle34009b2011-11-17 00:17:29 +0000295 arg3 : IThriftDictionary<SmallInt, string>;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000296 arg4 : TNumberz;
297 arg5 : Int64;
298 StartTick : Cardinal;
299 k : Integer;
300 proc : TThreadProcedure;
Jake Farrelle34009b2011-11-17 00:17:29 +0000301 hello, goodbye : IXtruct;
302 crazy : IInsanity;
303 looney : IInsanity;
304 first_map : IThriftDictionary<TNumberz, IInsanity>;
305 second_map : IThriftDictionary<TNumberz, IInsanity>;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000306
307begin
Jake Farrell27274222011-11-10 20:32:44 +0000308 client := TThriftTest.TClient.Create( FProtocol);
Jake Farrell7ae13e12011-10-18 14:35:26 +0000309 try
310 if not FTransport.IsOpen then
311 begin
312 FTransport.Open;
313 end;
314 except
315 on E: Exception do
316 begin
317 Console.WriteLine( E.Message );
318 Exit;
319 end;
320 end;
321
Jake Farrelle34009b2011-11-17 00:17:29 +0000322 // in-depth exception test
323 // (1) do we get an exception at all?
324 // (2) do we get the right exception?
325 // (3) does the exception contain the expected data?
326 StartTestGroup( 'testException');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000327 try
328 client.testException('Xception');
Jake Farrelle34009b2011-11-17 00:17:29 +0000329 Expect( FALSE, 'testException(''Xception''): must trow an exception');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000330 except
Jake Farrelle34009b2011-11-17 00:17:29 +0000331 on e:TXception do begin
332 Expect( e.ErrorCode = 1001, 'error code');
333 Expect( e.Message_ = 'This is an Xception', 'error message');
334 Console.WriteLine( ' = ' + IntToStr(e.ErrorCode) + ', ' + e.Message_ );
Jake Farrell7ae13e12011-10-18 14:35:26 +0000335 end;
Jake Farrelle34009b2011-11-17 00:17:29 +0000336 on e:TTransportException do Expect( FALSE, 'Unexpected : "'+e.ToString+'"');
337 on e:Exception do Expect( FALSE, 'Unexpected exception type "'+e.ClassName+'"');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000338 end;
339
Jake Farrelle34009b2011-11-17 00:17:29 +0000340 // simple things
341 StartTestGroup( 'simple Thrift calls');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000342 client.testVoid();
Jake Farrelle34009b2011-11-17 00:17:29 +0000343 Expect( TRUE, 'testVoid()'); // success := no exception
Jake Farrell7ae13e12011-10-18 14:35:26 +0000344
Jake Farrell7ae13e12011-10-18 14:35:26 +0000345 s := client.testString('Test');
Jake Farrelle34009b2011-11-17 00:17:29 +0000346 Expect( s = 'Test', 'testString(''Test'') = "'+s+'"');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000347
Jake Farrell7ae13e12011-10-18 14:35:26 +0000348 i8 := client.testByte(1);
Jake Farrelle34009b2011-11-17 00:17:29 +0000349 Expect( i8 = 1, 'testByte(1) = ' + IntToStr( i8 ));
Jake Farrell7ae13e12011-10-18 14:35:26 +0000350
Jake Farrell7ae13e12011-10-18 14:35:26 +0000351 i32 := client.testI32(-1);
Jake Farrelle34009b2011-11-17 00:17:29 +0000352 Expect( i32 = -1, 'testI32(-1) = ' + IntToStr(i32));
Jake Farrell7ae13e12011-10-18 14:35:26 +0000353
Jake Farrelle34009b2011-11-17 00:17:29 +0000354 Console.WriteLine('testI64(-34359738368)');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000355 i64 := client.testI64(-34359738368);
Jake Farrelle34009b2011-11-17 00:17:29 +0000356 Expect( i64 = -34359738368, 'testI64(-34359738368) = ' + IntToStr( i64));
Jake Farrell7ae13e12011-10-18 14:35:26 +0000357
Jake Farrelle34009b2011-11-17 00:17:29 +0000358 Console.WriteLine('testDouble(5.325098235)');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000359 dub := client.testDouble(5.325098235);
Jake Farrelle34009b2011-11-17 00:17:29 +0000360 Expect( abs(dub-5.325098235) < 1e-14, 'testDouble(5.325098235) = ' + FloatToStr( dub));
Jake Farrell7ae13e12011-10-18 14:35:26 +0000361
Jake Farrelle34009b2011-11-17 00:17:29 +0000362 // structs
363 StartTestGroup( 'testStruct');
364 Console.WriteLine('testStruct({''Zero'', 1, -3, -5})');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000365 o := TXtructImpl.Create;
366 o.String_thing := 'Zero';
367 o.Byte_thing := 1;
368 o.I32_thing := -3;
369 o.I64_thing := -5;
370 i := client.testStruct(o);
Jake Farrelle34009b2011-11-17 00:17:29 +0000371 Expect( i.String_thing = 'Zero', 'i.String_thing = "'+i.String_thing+'"');
372 Expect( i.Byte_thing = 1, 'i.Byte_thing = '+IntToStr(i.Byte_thing));
373 Expect( i.I32_thing = -3, 'i.I32_thing = '+IntToStr(i.I32_thing));
374 Expect( i.I64_thing = -5, 'i.I64_thing = '+IntToStr(i.I64_thing));
375 Expect( i.__isset_String_thing, 'i.__isset_String_thing = '+BoolToString(i.__isset_String_thing));
376 Expect( i.__isset_Byte_thing, 'i.__isset_Byte_thing = '+BoolToString(i.__isset_Byte_thing));
377 Expect( i.__isset_I32_thing, 'i.__isset_I32_thing = '+BoolToString(i.__isset_I32_thing));
378 Expect( i.__isset_I64_thing, 'i.__isset_I64_thing = '+BoolToString(i.__isset_I64_thing));
Jake Farrell7ae13e12011-10-18 14:35:26 +0000379
Jake Farrelle34009b2011-11-17 00:17:29 +0000380 // nested structs
381 StartTestGroup( 'testNest');
382 Console.WriteLine('testNest({1, {''Zero'', 1, -3, -5}, 5})');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000383 o2 := TXtruct2Impl.Create;
384 o2.Byte_thing := 1;
385 o2.Struct_thing := o;
386 o2.I32_thing := 5;
387 i2 := client.testNest(o2);
388 i := i2.Struct_thing;
Jake Farrelle34009b2011-11-17 00:17:29 +0000389 Expect( i.String_thing = 'Zero', 'i.String_thing = "'+i.String_thing+'"');
390 Expect( i.Byte_thing = 1, 'i.Byte_thing = '+IntToStr(i.Byte_thing));
391 Expect( i.I32_thing = -3, 'i.I32_thing = '+IntToStr(i.I32_thing));
392 Expect( i.I64_thing = -5, 'i.I64_thing = '+IntToStr(i.I64_thing));
393 Expect( i2.Byte_thing = 1, 'i2.Byte_thing = '+IntToStr(i2.Byte_thing));
394 Expect( i2.I32_thing = 5, 'i2.I32_thing = '+IntToStr(i2.I32_thing));
395 Expect( i.__isset_String_thing, 'i.__isset_String_thing = '+BoolToString(i.__isset_String_thing));
396 Expect( i.__isset_Byte_thing, 'i.__isset_Byte_thing = '+BoolToString(i.__isset_Byte_thing));
397 Expect( i.__isset_I32_thing, 'i.__isset_I32_thing = '+BoolToString(i.__isset_I32_thing));
398 Expect( i.__isset_I64_thing, 'i.__isset_I64_thing = '+BoolToString(i.__isset_I64_thing));
399 Expect( i2.__isset_Byte_thing, 'i2.__isset_Byte_thing');
400 Expect( i2.__isset_I32_thing, 'i2.__isset_I32_thing');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000401
Jake Farrelle34009b2011-11-17 00:17:29 +0000402 // map<type1,type2>: A map of strictly unique keys to values.
403 // Translates to an STL map, Java HashMap, PHP associative array, Python/Ruby dictionary, etc.
404 StartTestGroup( 'testMap');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000405 mapout := TThriftDictionaryImpl<Integer,Integer>.Create;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000406 for j := 0 to 4 do
407 begin
408 mapout.AddOrSetValue( j, j - 10);
409 end;
410 Console.Write('testMap({');
411 first := True;
412 for key in mapout.Keys do
413 begin
Jake Farrelle34009b2011-11-17 00:17:29 +0000414 if first
415 then first := False
416 else Console.Write( ', ' );
Jake Farrell7ae13e12011-10-18 14:35:26 +0000417 Console.Write( IntToStr( key) + ' => ' + IntToStr( mapout[key]));
418 end;
Jake Farrelle34009b2011-11-17 00:17:29 +0000419 Console.WriteLine('})');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000420
421 mapin := client.testMap( mapout );
Jake Farrelle34009b2011-11-17 00:17:29 +0000422 Expect( mapin.Count = mapout.Count, 'testMap: mapin.Count = mapout.Count');
423 for j := 0 to 4 do
424 begin
425 Expect( mapout.ContainsKey(j), 'testMap: mapout.ContainsKey('+IntToStr(j)+') = '+BoolToString(mapout.ContainsKey(j)));
426 end;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000427 for key in mapin.Keys do
428 begin
Jake Farrelle34009b2011-11-17 00:17:29 +0000429 Expect( mapin[key] = mapout[key], 'testMap: '+IntToStr(key) + ' => ' + IntToStr( mapin[key]));
430 Expect( mapin[key] = key - 10, 'testMap: mapin['+IntToStr(key)+'] = '+IntToStr( mapin[key]));
Jake Farrell7ae13e12011-10-18 14:35:26 +0000431 end;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000432
Jake Farrelle34009b2011-11-17 00:17:29 +0000433
434 // set<type>: An unordered set of unique elements.
435 // Translates to an STL set, Java HashSet, set in Python, etc.
436 // Note: PHP does not support sets, so it is treated similar to a List
437 StartTestGroup( 'testSet');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000438 setout := THashSetImpl<Integer>.Create;
439 for j := -2 to 2 do
440 begin
441 setout.Add( j );
442 end;
443 Console.Write('testSet({');
444 first := True;
445 for j in setout do
446 begin
Jake Farrelle34009b2011-11-17 00:17:29 +0000447 if first
448 then first := False
449 else Console.Write(', ');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000450 Console.Write(IntToStr( j));
451 end;
Jake Farrelle34009b2011-11-17 00:17:29 +0000452 Console.WriteLine('})');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000453
Jake Farrell7ae13e12011-10-18 14:35:26 +0000454 setin := client.testSet(setout);
Jake Farrelle34009b2011-11-17 00:17:29 +0000455 Expect( setin.Count = setout.Count, 'testSet: setin.Count = setout.Count');
456 Expect( setin.Count = 5, 'testSet: setin.Count = '+IntToStr(setin.Count));
457 for j := -2 to 2 do // unordered, we can't rely on the order => test for known elements only
Jake Farrell7ae13e12011-10-18 14:35:26 +0000458 begin
Jake Farrelle34009b2011-11-17 00:17:29 +0000459 Expect( setin.Contains(j), 'testSet: setin.Contains('+IntToStr(j)+') => '+BoolToString(setin.Contains(j)));
460 end;
461
462 // list<type>: An ordered list of elements.
463 // Translates to an STL vector, Java ArrayList, native arrays in scripting languages, etc.
464 StartTestGroup( 'testList');
465 listout := TThriftListImpl<Integer>.Create;
466 listout.Add( +1);
467 listout.Add( -2);
468 listout.Add( +3);
469 listout.Add( -4);
470 listout.Add( 0);
471 Console.Write('testList({');
472 first := True;
473 for j in listout do
Jake Farrell7ae13e12011-10-18 14:35:26 +0000474 begin
Jake Farrelle34009b2011-11-17 00:17:29 +0000475 if first
476 then first := False
477 else Console.Write(', ');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000478 Console.Write(IntToStr( j));
479 end;
Jake Farrelle34009b2011-11-17 00:17:29 +0000480 Console.WriteLine('})');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000481
Jake Farrelle34009b2011-11-17 00:17:29 +0000482 listin := client.testList(listout);
483 Expect( listin.Count = listout.Count, 'testList: listin.Count = listout.Count');
484 Expect( listin.Count = 5, 'testList: listin.Count = '+IntToStr(listin.Count));
485 Expect( listin[0] = +1, 'listin[0] = '+IntToStr( listin[0]));
486 Expect( listin[1] = -2, 'listin[1] = '+IntToStr( listin[1]));
487 Expect( listin[2] = +3, 'listin[2] = '+IntToStr( listin[2]));
488 Expect( listin[3] = -4, 'listin[3] = '+IntToStr( listin[3]));
489 Expect( listin[4] = 0, 'listin[4] = '+IntToStr( listin[4]));
490
491 // enums
Jake Farrell7ae13e12011-10-18 14:35:26 +0000492 ret := client.testEnum(TNumberz.ONE);
Jake Farrelle34009b2011-11-17 00:17:29 +0000493 Expect( ret = TNumberz.ONE, 'testEnum(ONE) = '+IntToStr(Ord(ret)));
Jake Farrell7ae13e12011-10-18 14:35:26 +0000494
Jake Farrell7ae13e12011-10-18 14:35:26 +0000495 ret := client.testEnum(TNumberz.TWO);
Jake Farrelle34009b2011-11-17 00:17:29 +0000496 Expect( ret = TNumberz.TWO, 'testEnum(TWO) = '+IntToStr(Ord(ret)));
Jake Farrell7ae13e12011-10-18 14:35:26 +0000497
Jake Farrell7ae13e12011-10-18 14:35:26 +0000498 ret := client.testEnum(TNumberz.THREE);
Jake Farrelle34009b2011-11-17 00:17:29 +0000499 Expect( ret = TNumberz.THREE, 'testEnum(THREE) = '+IntToStr(Ord(ret)));
Jake Farrell7ae13e12011-10-18 14:35:26 +0000500
Jake Farrell7ae13e12011-10-18 14:35:26 +0000501 ret := client.testEnum(TNumberz.FIVE);
Jake Farrelle34009b2011-11-17 00:17:29 +0000502 Expect( ret = TNumberz.FIVE, 'testEnum(FIVE) = '+IntToStr(Ord(ret)));
Jake Farrell7ae13e12011-10-18 14:35:26 +0000503
Jake Farrell7ae13e12011-10-18 14:35:26 +0000504 ret := client.testEnum(TNumberz.EIGHT);
Jake Farrelle34009b2011-11-17 00:17:29 +0000505 Expect( ret = TNumberz.EIGHT, 'testEnum(EIGHT) = '+IntToStr(Ord(ret)));
Jake Farrell7ae13e12011-10-18 14:35:26 +0000506
Jake Farrelle34009b2011-11-17 00:17:29 +0000507
508 // typedef
Jake Farrell7ae13e12011-10-18 14:35:26 +0000509 uid := client.testTypedef(309858235082523);
Jake Farrelle34009b2011-11-17 00:17:29 +0000510 Expect( uid = 309858235082523, 'testTypedef(309858235082523) = '+IntToStr(uid));
Jake Farrell7ae13e12011-10-18 14:35:26 +0000511
Jake Farrelle34009b2011-11-17 00:17:29 +0000512
513 // maps of maps
514 StartTestGroup( 'testMapMap(1)');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000515 mm := client.testMapMap(1);
516 Console.Write(' = {');
517 for key in mm.Keys do
518 begin
519 Console.Write( IntToStr( key) + ' => {');
520 m2 := mm[key];
521 for k2 in m2.Keys do
522 begin
523 Console.Write( IntToStr( k2) + ' => ' + IntToStr( m2[k2]) + ', ');
524 end;
525 Console.Write('}, ');
526 end;
527 Console.WriteLine('}');
528
Jake Farrelle34009b2011-11-17 00:17:29 +0000529 // verify result data
530 Expect( mm.Count = 2, 'mm.Count = '+IntToStr(mm.Count));
531 pos := mm[4];
532 neg := mm[-4];
533 for j := 1 to 4 do
534 begin
535 Expect( pos[j] = j, 'pos[j] = '+IntToStr(pos[j]));
536 Expect( neg[-j] = -j, 'neg[-j] = '+IntToStr(neg[-j]));
537 end;
538
539
540
541 // insanity
542 StartTestGroup( 'testInsanity');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000543 insane := TInsanityImpl.Create;
544 insane.UserMap := TThriftDictionaryImpl<TNumberz, Int64>.Create;
545 insane.UserMap.AddOrSetValue( TNumberz.FIVE, 5000);
546 truck := TXtructImpl.Create;
547 truck.String_thing := 'Truck';
548 truck.Byte_thing := 8;
549 truck.I32_thing := 8;
550 truck.I64_thing := 8;
551 insane.Xtructs := TThriftListImpl<IXtruct>.Create;
552 insane.Xtructs.Add( truck );
Jake Farrell7ae13e12011-10-18 14:35:26 +0000553 whoa := client.testInsanity( insane );
554 Console.Write(' = {');
555 for key64 in whoa.Keys do
556 begin
557 val := whoa[key64];
558 Console.Write( IntToStr( key64) + ' => {');
559 for k2_2 in val.Keys do
560 begin
561 v2 := val[k2_2];
562 Console.Write( IntToStr( Integer( k2_2)) + ' => {');
563 userMap := v2.UserMap;
564 Console.Write('{');
565 if userMap <> nil then
566 begin
567 for k3 in userMap.Keys do
568 begin
569 Console.Write( IntToStr( Integer( k3)) + ' => ' + IntToStr( userMap[k3]) + ', ');
570 end;
571 end else
572 begin
573 Console.Write('null');
574 end;
575 Console.Write('}, ');
576 xtructs := v2.Xtructs;
577 Console.Write('{');
578
579 if xtructs <> nil then
580 begin
581 for x in xtructs do
582 begin
583 Console.Write('{"' + x.String_thing + '", ' +
584 IntToStr( x.Byte_thing) + ', ' +
585 IntToStr( x.I32_thing) + ', ' +
586 IntToStr( x.I32_thing) + '}, ');
587 end;
588 end else
589 begin
590 Console.Write('null');
591 end;
592 Console.Write('}');
593 Console.Write('}, ');
594 end;
595 Console.Write('}, ');
596 end;
597 Console.WriteLine('}');
598
Jake Farrelle34009b2011-11-17 00:17:29 +0000599 // verify result data
600 Expect( whoa.Count = 2, 'whoa.Count = '+IntToStr(whoa.Count));
601 //
602 first_map := whoa[1];
603 second_map := whoa[2];
604 Expect( first_map.Count = 2, 'first_map.Count = '+IntToStr(first_map.Count));
605 Expect( second_map.Count = 1, 'second_map.Count = '+IntToStr(second_map.Count));
606 //
607 looney := second_map[TNumberz.SIX];
608 Expect( Assigned(looney), 'Assigned(looney) = '+BoolToString(Assigned(looney)));
609 Expect( not looney.__isset_UserMap, 'looney.__isset_UserMap = '+BoolToString(looney.__isset_UserMap));
610 Expect( not looney.__isset_Xtructs, 'looney.__isset_Xtructs = '+BoolToString(looney.__isset_Xtructs));
611 //
612 for ret in [TNumberz.SIX, TNumberz.THREE] do begin
613 crazy := first_map[ret];
614 Console.WriteLine('first_map['+intToStr(Ord(ret))+']');
615
616 Expect( crazy.__isset_UserMap, 'crazy.__isset_UserMap = '+BoolToString(crazy.__isset_UserMap));
617 Expect( crazy.__isset_Xtructs, 'crazy.__isset_Xtructs = '+BoolToString(crazy.__isset_Xtructs));
618
619 Expect( crazy.UserMap.Count = 2, 'crazy.UserMap.Count = '+IntToStr(crazy.UserMap.Count));
620 Expect( crazy.UserMap[TNumberz.FIVE] = 5, 'crazy.UserMap[TNumberz.FIVE] = '+IntToStr(crazy.UserMap[TNumberz.FIVE]));
621 Expect( crazy.UserMap[TNumberz.EIGHT] = 8, 'crazy.UserMap[TNumberz.EIGHT] = '+IntToStr(crazy.UserMap[TNumberz.EIGHT]));
622
623 Expect( crazy.Xtructs.Count = 2, 'crazy.Xtructs.Count = '+IntToStr(crazy.Xtructs.Count));
624 goodbye := crazy.Xtructs[0]; // lists are ordered, so we are allowed to assume this order
625 hello := crazy.Xtructs[1];
626
627 Expect( goodbye.String_thing = 'Goodbye4', 'goodbye.String_thing = "'+goodbye.String_thing+'"');
628 Expect( goodbye.Byte_thing = 4, 'goodbye.Byte_thing = '+IntToStr(goodbye.Byte_thing));
629 Expect( goodbye.I32_thing = 4, 'goodbye.I32_thing = '+IntToStr(goodbye.I32_thing));
630 Expect( goodbye.I64_thing = 4, 'goodbye.I64_thing = '+IntToStr(goodbye.I64_thing));
631 Expect( goodbye.__isset_String_thing, 'goodbye.__isset_String_thing = '+BoolToString(goodbye.__isset_String_thing));
632 Expect( goodbye.__isset_Byte_thing, 'goodbye.__isset_Byte_thing = '+BoolToString(goodbye.__isset_Byte_thing));
633 Expect( goodbye.__isset_I32_thing, 'goodbye.__isset_I32_thing = '+BoolToString(goodbye.__isset_I32_thing));
634 Expect( goodbye.__isset_I64_thing, 'goodbye.__isset_I64_thing = '+BoolToString(goodbye.__isset_I64_thing));
635
636 Expect( hello.String_thing = 'hello', 'hello.String_thing = "'+hello.String_thing+'"');
637 Expect( hello.Byte_thing = 2, 'hello.Byte_thing = '+IntToStr(hello.Byte_thing));
638 Expect( hello.I32_thing = 2, 'hello.I32_thing = '+IntToStr(hello.I32_thing));
639 Expect( hello.I64_thing = 2, 'hello.I64_thing = '+IntToStr(hello.I64_thing));
640 Expect( hello.__isset_String_thing, 'hello.__isset_String_thing = '+BoolToString(hello.__isset_String_thing));
641 Expect( hello.__isset_Byte_thing, 'hello.__isset_Byte_thing = '+BoolToString(hello.__isset_Byte_thing));
642 Expect( hello.__isset_I32_thing, 'hello.__isset_I32_thing = '+BoolToString(hello.__isset_I32_thing));
643 Expect( hello.__isset_I64_thing, 'hello.__isset_I64_thing = '+BoolToString(hello.__isset_I64_thing));
644 end;
645
646
647 // multi args
648 StartTestGroup( 'testMulti');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000649 arg0 := 1;
650 arg1 := 2;
651 arg2 := High(Int64);
Jake Farrelle34009b2011-11-17 00:17:29 +0000652 arg3 := TThriftDictionaryImpl<SmallInt, string>.Create;
653 arg3.AddOrSetValue( 1, 'one');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000654 arg4 := TNumberz.FIVE;
655 arg5 := 5000000;
656 Console.WriteLine('Test Multi(' + IntToStr( arg0) + ',' +
657 IntToStr( arg1) + ',' + IntToStr( arg2) + ',' +
Jake Farrelle34009b2011-11-17 00:17:29 +0000658 arg3.ToString + ',' + IntToStr( Integer( arg4)) + ',' +
Jake Farrell7ae13e12011-10-18 14:35:26 +0000659 IntToStr( arg5) + ')');
660
Jake Farrelle34009b2011-11-17 00:17:29 +0000661 i := client.testMulti( arg0, arg1, arg2, arg3, arg4, arg5);
662 Expect( i.String_thing = 'Hello2', 'testMulti: i.String_thing = "'+i.String_thing+'"');
663 Expect( i.Byte_thing = arg0, 'testMulti: i.Byte_thing = '+IntToStr(i.Byte_thing));
664 Expect( i.I32_thing = arg1, 'testMulti: i.I32_thing = '+IntToStr(i.I32_thing));
665 Expect( i.I64_thing = arg2, 'testMulti: i.I64_thing = '+IntToStr(i.I64_thing));
666 Expect( i.__isset_String_thing, 'testMulti: i.__isset_String_thing = '+BoolToString(i.__isset_String_thing));
667 Expect( i.__isset_Byte_thing, 'testMulti: i.__isset_Byte_thing = '+BoolToString(i.__isset_Byte_thing));
668 Expect( i.__isset_I32_thing, 'testMulti: i.__isset_I32_thing = '+BoolToString(i.__isset_I32_thing));
669 Expect( i.__isset_I64_thing, 'testMulti: i.__isset_I64_thing = '+BoolToString(i.__isset_I64_thing));
670
671 // multi exception
672 StartTestGroup( 'testMultiException(1)');
673 try
674 i := client.testMultiException( 'need more pizza', 'run out of beer');
675 Expect( i.String_thing = 'run out of beer', 'i.String_thing = "' +i.String_thing+ '"');
676 Expect( i.__isset_String_thing, 'i.__isset_String_thing = '+BoolToString(i.__isset_String_thing));
677 Expect( not i.__isset_Byte_thing, 'i.__isset_Byte_thing = '+BoolToString(i.__isset_Byte_thing));
678 Expect( not i.__isset_I32_thing, 'i.__isset_I32_thing = '+BoolToString(i.__isset_I32_thing));
679 Expect( not i.__isset_I64_thing, 'i.__isset_I64_thing = '+BoolToString(i.__isset_I64_thing));
680 except
681 on e:Exception do Expect( FALSE, 'Unexpected exception "'+e.ClassName+'"');
682 end;
683
684 StartTestGroup( 'testMultiException(Xception)');
685 try
686 i := client.testMultiException( 'Xception', 'second test');
687 Expect( FALSE, 'testMultiException(''Xception''): must trow an exception');
688 except
689 on x:TXception do begin
690 Expect( x.__isset_ErrorCode, 'x.__isset_ErrorCode = '+BoolToString(x.__isset_ErrorCode));
691 Expect( x.__isset_Message_, 'x.__isset_Message_ = '+BoolToString(x.__isset_Message_));
692 Expect( x.ErrorCode = 1001, 'x.ErrorCode = '+IntToStr(x.ErrorCode));
693 Expect( x.Message_ = 'This is an Xception', 'x.Message = "'+x.Message_+'"');
694 end;
695 on e:Exception do Expect( FALSE, 'Unexpected exception "'+e.ClassName+'"');
696 end;
697
698 StartTestGroup( 'testMultiException(Xception2)');
699 try
700 i := client.testMultiException( 'Xception2', 'third test');
701 Expect( FALSE, 'testMultiException(''Xception2''): must trow an exception');
702 except
703 on x:TXception2 do begin
704 Expect( x.__isset_ErrorCode, 'x.__isset_ErrorCode = '+BoolToString(x.__isset_ErrorCode));
705 Expect( x.__isset_Struct_thing, 'x.__isset_Struct_thing = '+BoolToString(x.__isset_Struct_thing));
706 Expect( x.ErrorCode = 2002, 'x.ErrorCode = '+IntToStr(x.ErrorCode));
707 Expect( x.Struct_thing.String_thing = 'This is an Xception2', 'x.Struct_thing.String_thing = "'+x.Struct_thing.String_thing+'"');
708 Expect( x.Struct_thing.__isset_String_thing, 'x.Struct_thing.__isset_String_thing = '+BoolToString(x.Struct_thing.__isset_String_thing));
709 Expect( not x.Struct_thing.__isset_Byte_thing, 'x.Struct_thing.__isset_Byte_thing = '+BoolToString(x.Struct_thing.__isset_Byte_thing));
710 Expect( not x.Struct_thing.__isset_I32_thing, 'x.Struct_thing.__isset_I32_thing = '+BoolToString(x.Struct_thing.__isset_I32_thing));
711 Expect( not x.Struct_thing.__isset_I64_thing, 'x.Struct_thing.__isset_I64_thing = '+BoolToString(x.Struct_thing.__isset_I64_thing));
712 end;
713 on e:Exception do Expect( FALSE, 'Unexpected exception "'+e.ClassName+'"');
714 end;
715
716
717 // oneway functions
718 StartTestGroup( 'Test Oneway(1)');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000719 client.testOneway(1);
Jake Farrelle34009b2011-11-17 00:17:29 +0000720 Expect( TRUE, 'Test Oneway(1)'); // success := no exception
Jake Farrell7ae13e12011-10-18 14:35:26 +0000721
Jake Farrelle34009b2011-11-17 00:17:29 +0000722 // call time
723 StartTestGroup( 'Test Calltime()');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000724 StartTick := GetTIckCount;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000725 for k := 0 to 1000 - 1 do
726 begin
727 client.testVoid();
728 end;
729 Console.WriteLine(' = ' + FloatToStr( (GetTickCount - StartTick) / 1000 ) + ' ms a testVoid() call' );
730
Jake Farrelle34009b2011-11-17 00:17:29 +0000731 // no more tests here
732 StartTestGroup( '');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000733end;
734
Jake Farrell27274222011-11-10 20:32:44 +0000735
736procedure TClientThread.JSONProtocolReadWriteTest;
737// Tests only then read/write procedures of the JSON protocol
738// All tests succeed, if we can read what we wrote before
739// Note that passing this test does not imply, that our JSON is really compatible to what
740// other clients or servers expect as the real JSON. This is beyond the scope of this test.
741var prot : IProtocol;
742 stm : TStringStream;
743 list : IList;
744 binary, binRead : TBytes;
745 i,iErr : Integer;
746const
747 TEST_SHORT = ShortInt( $FE);
748 TEST_SMALL = SmallInt( $FEDC);
749 TEST_LONG = LongInt( $FEDCBA98);
750 TEST_I64 = Int64( $FEDCBA9876543210);
751 TEST_DOUBLE = -1.234e-56;
752 DELTA_DOUBLE = TEST_DOUBLE * 1e-14;
753 TEST_STRING = 'abc-'#$00E4#$00f6#$00fc; // german umlauts (en-us: "funny chars")
754begin
755 stm := TStringStream.Create;
756 try
Jake Farrelle34009b2011-11-17 00:17:29 +0000757 StartTestGroup( 'JsonProtocolTest'); // no more tests here
758
Jake Farrell27274222011-11-10 20:32:44 +0000759 // prepare binary data
760 SetLength( binary, $100);
761 for i := Low(binary) to High(binary) do binary[i] := i;
762
763 // output setup
764 prot := TJSONProtocolImpl.Create(
765 TStreamTransportImpl.Create(
766 nil, TThriftStreamAdapterDelphi.Create( stm, FALSE)));
767
768 // write
769 prot.WriteListBegin( TListImpl.Create( TType.String_, 9));
770 prot.WriteBool( TRUE);
771 prot.WriteBool( FALSE);
772 prot.WriteByte( TEST_SHORT);
773 prot.WriteI16( TEST_SMALL);
774 prot.WriteI32( TEST_LONG);
775 prot.WriteI64( TEST_I64);
776 prot.WriteDouble( TEST_DOUBLE);
777 prot.WriteString( TEST_STRING);
778 prot.WriteBinary( binary);
779 prot.WriteListEnd;
780
781 // input setup
782 Expect( stm.Position = stm.Size, 'Stream position/length after write');
783 stm.Position := 0;
784 prot := TJSONProtocolImpl.Create(
785 TStreamTransportImpl.Create(
786 TThriftStreamAdapterDelphi.Create( stm, FALSE), nil));
787
788 // read and compare
789 list := prot.ReadListBegin;
790 Expect( list.ElementType = TType.String_, 'list element type');
791 Expect( list.Count = 9, 'list element count');
792 Expect( prot.ReadBool, 'WriteBool/ReadBool: TRUE');
793 Expect( not prot.ReadBool, 'WriteBool/ReadBool: FALSE');
794 Expect( prot.ReadByte = TEST_SHORT, 'WriteByte/ReadByte');
795 Expect( prot.ReadI16 = TEST_SMALL, 'WriteI16/ReadI16');
796 Expect( prot.ReadI32 = TEST_LONG, 'WriteI32/ReadI32');
797 Expect( prot.ReadI64 = TEST_I64, 'WriteI64/ReadI64');
798 Expect( abs(prot.ReadDouble-TEST_DOUBLE) < abs(DELTA_DOUBLE), 'WriteDouble/ReadDouble');
799 Expect( prot.ReadString = TEST_STRING, 'WriteString/ReadString');
800 binRead := prot.ReadBinary;
801 prot.ReadListEnd;
802
803 // test binary data
804 Expect( Length(binary) = Length(binRead), 'Binary data length check');
805 iErr := -1;
806 for i := Low(binary) to High(binary) do begin
807 if binary[i] <> binRead[i] then begin
808 iErr := i;
809 Break;
810 end;
811 end;
812 if iErr < 0
813 then Expect( TRUE, 'Binary data check ('+IntToStr(Length(binary))+' Bytes)')
814 else Expect( FALSE, 'Binary data check at offset '+IntToStr(iErr));
815
816 Expect( stm.Position = stm.Size, 'Stream position after read');
817
818 finally
819 stm.Free;
820 prot := nil; //-> Release
Jake Farrelle34009b2011-11-17 00:17:29 +0000821 StartTestGroup( ''); // no more tests here
822 end;
823end;
824
825
826procedure TClientThread.StartTestGroup( const aGroup : string);
827begin
828 FTestGroup := aGroup;
829 if FTestGroup <> '' then begin
830 Console.WriteLine('');
831 Console.WriteLine( aGroup+' tests');
832 Console.WriteLine( StringOfChar('-',60));
Jake Farrell27274222011-11-10 20:32:44 +0000833 end;
834end;
835
836
837procedure TClientThread.Expect( aTestResult : Boolean; const aTestInfo : string);
838begin
839 if aTestResult then begin
840 Inc(FSuccesses);
Jake Farrelle34009b2011-11-17 00:17:29 +0000841 Console.WriteLine( aTestInfo+': passed');
Jake Farrell27274222011-11-10 20:32:44 +0000842 end
843 else begin
Jake Farrelle34009b2011-11-17 00:17:29 +0000844 FErrors.Add( FTestGroup+': '+aTestInfo);
845 Console.WriteLine( aTestInfo+': *** FAILED ***');
846
847 // We have a failed test!
848 // -> issue DebugBreak ONLY if a debugger is attached,
849 // -> unhandled DebugBreaks would cause Windows to terminate the app otherwise
850 if IsDebuggerPresent then asm int 3 end;
Jake Farrell27274222011-11-10 20:32:44 +0000851 end;
852end;
853
854
Jake Farrelle34009b2011-11-17 00:17:29 +0000855procedure TClientThread.ReportResults;
856var nTotal : Integer;
857 sLine : string;
858begin
859 // prevent us from stupid DIV/0 errors
860 nTotal := FSuccesses + FErrors.Count;
861 if nTotal = 0 then begin
862 Console.WriteLine('No results logged');
863 Exit;
864 end;
865
866 Console.WriteLine('');
867 Console.WriteLine( StringOfChar('=',60));
868 Console.WriteLine( IntToStr(nTotal)+' tests performed');
869 Console.WriteLine( IntToStr(FSuccesses)+' tests succeeded ('+IntToStr(round(100*FSuccesses/nTotal))+'%)');
870 Console.WriteLine( IntToStr(FErrors.Count)+' tests failed ('+IntToStr(round(100*FErrors.Count/nTotal))+'%)');
871 Console.WriteLine( StringOfChar('=',60));
872 if FErrors.Count > 0 then begin
873 Console.WriteLine('FAILED TESTS:');
874 for sLine in FErrors do Console.WriteLine('- '+sLine);
875 Console.WriteLine( StringOfChar('=',60));
876 end;
877 Console.WriteLine('');
878end;
879
880
Jake Farrell27274222011-11-10 20:32:44 +0000881constructor TClientThread.Create(ATransport: ITransport; AProtocol : IProtocol; ANumIteration: Integer);
Jake Farrell7ae13e12011-10-18 14:35:26 +0000882begin
883 inherited Create( True );
884 FNumIteration := ANumIteration;
885 FTransport := ATransport;
Jake Farrell27274222011-11-10 20:32:44 +0000886 FProtocol := AProtocol;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000887 FConsole := TThreadConsole.Create( Self );
Jake Farrelle34009b2011-11-17 00:17:29 +0000888
889 // error list: keep correct order, allow for duplicates
890 FErrors := TStringList.Create;
891 FErrors.Sorted := FALSE;
892 FErrors.Duplicates := dupAccept;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000893end;
894
895destructor TClientThread.Destroy;
896begin
Jake Farrelle34009b2011-11-17 00:17:29 +0000897 FreeAndNil( FConsole);
898 FreeAndNil( FErrors);
Jake Farrell7ae13e12011-10-18 14:35:26 +0000899 inherited;
900end;
901
902procedure TClientThread.Execute;
903var
904 i : Integer;
905 proc : TThreadProcedure;
906begin
Jake Farrelle34009b2011-11-17 00:17:29 +0000907 // perform all tests
908 try
909 for i := 0 to FNumIteration - 1 do
910 begin
911 ClientTest;
912 JSONProtocolReadWriteTest;
913 end;
914 except
915 on e:Exception do Expect( FALSE, 'unexpected exception: "'+e.message+'"');
Jake Farrell7ae13e12011-10-18 14:35:26 +0000916 end;
917
Jake Farrelle34009b2011-11-17 00:17:29 +0000918 // report the outcome
919 ReportResults;
920
921 // shutdown
Jake Farrell7ae13e12011-10-18 14:35:26 +0000922 proc := procedure
923 begin
924 if FTransport <> nil then
925 begin
926 FTransport.Close;
927 FTransport := nil;
928 end;
929 end;
930
931 Synchronize( proc );
932end;
933
934{ TThreadConsole }
935
936constructor TThreadConsole.Create(AThread: TThread);
937begin
938 FThread := AThread;
939end;
940
941procedure TThreadConsole.Write(const S: string);
942var
943 proc : TThreadProcedure;
944begin
945 proc := procedure
946 begin
947 Console.Write( S );
948 end;
949 TThread.Synchronize( FThread, proc);
950end;
951
952procedure TThreadConsole.WriteLine(const S: string);
953var
954 proc : TThreadProcedure;
955begin
956 proc := procedure
957 begin
958 Console.WriteLine( S );
959 end;
960 TThread.Synchronize( FThread, proc);
961end;
962
963initialization
964begin
965 TTestClient.FNumIteration := 1;
966 TTestClient.FNumThread := 1;
967end;
968
969end.