testjsonparser.pp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. {
  2. This file is part of the Free Component Library
  3. JSON FPCUNit test for parser
  4. Copyright (c) 2007 by Michael Van Canneyt [email protected]
  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. {$mode objfpc}
  12. {$h+}
  13. unit testjsonparser;
  14. interface
  15. uses
  16. Classes, SysUtils, fpcunit, testutils, testregistry,fpjson,
  17. jsonParser,testjsondata;
  18. type
  19. { TTestParser }
  20. TTestParser = class(TTestJSON)
  21. private
  22. procedure CallNoHandlerStream;
  23. procedure DoTestError(S: String);
  24. procedure DoTestFloat(F: TJSONFloat); overload;
  25. procedure DoTestFloat(F: TJSONFloat; S: String); overload;
  26. procedure DoTestObject(S: String; const ElNames: array of String; DoJSONTest : Boolean = True);
  27. procedure DoTestString(S : String);
  28. procedure DoTestArray(S: String; ACount: Integer);
  29. Procedure DoTestClass(S : String; AClass : TJSONDataClass);
  30. procedure CallNoHandler;
  31. published
  32. procedure TestEmpty;
  33. procedure TestNull;
  34. procedure TestTrue;
  35. procedure TestFalse;
  36. procedure TestFloat;
  37. procedure TestInteger;
  38. procedure TestInt64;
  39. procedure TestString;
  40. procedure TestArray;
  41. procedure TestObject;
  42. procedure TestMixed;
  43. procedure TestErrors;
  44. Procedure TestClasses;
  45. Procedure TestHandler;
  46. Procedure TestNoHandlerError;
  47. Procedure TestHandlerResult;
  48. Procedure TestHandlerResultStream;
  49. end;
  50. implementation
  51. procedure TTestParser.TestEmpty;
  52. Var
  53. P : TJSONParser;
  54. J : TJSONData;
  55. begin
  56. P:=TJSONParser.Create('');
  57. Try
  58. J:=P.Parse;
  59. If (J<>Nil) then
  60. Fail('Empty returns Nil');
  61. Finally
  62. FreeAndNil(J);
  63. FreeAndNil(P);
  64. end;
  65. end;
  66. procedure TTestParser.TestInteger;
  67. Var
  68. P : TJSONParser;
  69. J : TJSONData;
  70. begin
  71. P:=TJSONParser.Create('1');
  72. Try
  73. J:=P.Parse;
  74. If (J=Nil) then
  75. Fail('Parse of 1 fails');
  76. TestJSONType(J,jtNumber);
  77. TestAsInteger(J,1);
  78. Finally
  79. FreeAndNil(J);
  80. FreeAndNil(P);
  81. end;
  82. end;
  83. procedure TTestParser.TestInt64;
  84. Var
  85. P : TJSONParser;
  86. J : TJSONData;
  87. begin
  88. P:=TJSONParser.Create('123456789012345');
  89. Try
  90. J:=P.Parse;
  91. If (J=Nil) then
  92. Fail('Parse of 123456789012345 fails');
  93. TestJSONType(J,jtNumber);
  94. TestAsInt64(J,123456789012345);
  95. Finally
  96. FreeAndNil(J);
  97. FreeAndNil(P);
  98. end;
  99. end;
  100. procedure TTestParser.TestNull;
  101. Var
  102. P : TJSONParser;
  103. J : TJSONData;
  104. begin
  105. P:=TJSONParser.Create('null');
  106. Try
  107. J:=P.Parse;
  108. If (J=Nil) then
  109. Fail('Parse of null fails');
  110. TestJSONType(J,jtNull);
  111. Finally
  112. FreeAndNil(J);
  113. FreeAndNil(P);
  114. end;
  115. end;
  116. procedure TTestParser.TestTrue;
  117. Var
  118. P : TJSONParser;
  119. J : TJSONData;
  120. begin
  121. P:=TJSONParser.Create('true');
  122. Try
  123. J:=P.Parse;
  124. If (J=Nil) then
  125. Fail('Parse of True fails');
  126. TestJSONType(J,jtBoolean);
  127. TestAsBoolean(J,True);
  128. Finally
  129. FreeAndNil(J);
  130. FreeAndNil(P);
  131. end;
  132. end;
  133. procedure TTestParser.TestFalse;
  134. Var
  135. P : TJSONParser;
  136. J : TJSONData;
  137. begin
  138. P:=TJSONParser.Create('false');
  139. Try
  140. J:=P.Parse;
  141. If (J=Nil) then
  142. Fail('Parse of False fails');
  143. TestJSONType(J,jtBoolean);
  144. TestAsBoolean(J,False);
  145. Finally
  146. FreeAndNil(J);
  147. FreeAndNil(P);
  148. end;
  149. end;
  150. procedure TTestParser.TestFloat;
  151. begin
  152. DoTestFloat(1.2);
  153. DoTestFloat(-1.2);
  154. DoTestFloat(0);
  155. DoTestFloat(1.2e1);
  156. DoTestFloat(-1.2e1);
  157. DoTestFloat(0);
  158. DoTestFloat(1.2,'1.2');
  159. DoTestFloat(-1.2,'-1.2');
  160. DoTestFloat(0,'0.0');
  161. end;
  162. procedure TTestParser.TestString;
  163. begin
  164. DoTestString('A string');
  165. DoTestString('');
  166. DoTestString('\"');
  167. end;
  168. procedure TTestParser.TestArray;
  169. Var
  170. S1,S2,S3 : String;
  171. begin
  172. DoTestArray('[]',0);
  173. DoTestArray('[null]',1);
  174. DoTestArray('[true]',1);
  175. DoTestArray('[false]',1);
  176. DoTestArray('[1]',1);
  177. DoTestArray('[1, 2]',2);
  178. DoTestArray('[1, 2, 3]',3);
  179. DoTestArray('[1234567890123456]',1);
  180. DoTestArray('[1234567890123456, 2234567890123456]',2);
  181. DoTestArray('[1234567890123456, 2234567890123456, 3234567890123456]',3);
  182. Str(Double(1.2),S1);
  183. Delete(S1,1,1);
  184. Str(Double(2.3),S2);
  185. Delete(S2,1,1);
  186. Str(Double(3.4),S3);
  187. Delete(S3,1,1);
  188. DoTestArray('['+S1+']',1);
  189. DoTestArray('['+S1+', '+S2+']',2);
  190. DoTestArray('['+S1+', '+S2+', '+S3+']',3);
  191. DoTestArray('["A string"]',1);
  192. DoTestArray('["A string", "Another string"]',2);
  193. DoTestArray('["A string", "Another string", "Yet another string"]',3);
  194. DoTestArray('[null, false]',2);
  195. DoTestArray('[true, false]',2);
  196. DoTestArray('[null, 1]',2);
  197. DoTestArray('[1, "A string"]',2);
  198. DoTestArray('[1, []]',2);
  199. DoTestArray('[1, [1, 2]]',2);
  200. end;
  201. procedure TTestParser.TestMixed;
  202. Const
  203. SAddr ='{ "addressbook": { "name": "Mary Lebow", '+
  204. ' "address": {'+
  205. ' "street": "5 Main Street",'+LineEnding+
  206. ' "city": "San Diego, CA",'+LineEnding+
  207. ' "zip": 91912,'+LineEnding+
  208. ' },'+LineEnding+
  209. ' "phoneNumbers": [ '+LineEnding+
  210. ' "619 332-3452",'+LineEnding+
  211. ' "664 223-4667"'+LineEnding+
  212. ' ]'+LineEnding+
  213. ' }'+LineEnding+
  214. '}';
  215. begin
  216. DoTestArray('[1, {}]',2);
  217. DoTestArray('[1, { "a" : 1 }]',2);
  218. DoTestArray('[1, { "a" : 1 }, 1]',3);
  219. DoTestObject('{ "a" : [1, 2] }',['a']);
  220. DoTestObject('{ "a" : [1, 2], "B" : { "c" : "d" } }',['a','B']);
  221. DoTestObject(SAddr,['addressbook'],False);
  222. end;
  223. procedure TTestParser.TestObject;
  224. begin
  225. DoTestObject('{}',[]);
  226. DoTestObject('{ "a" : 1 }',['a']);
  227. DoTestObject('{ "a" : 1, "B" : "String" }',['a','B']);
  228. DoTestObject('{ "a" : 1, "B" : {} }',['a','B']);
  229. DoTestObject('{ "a" : 1, "B" : { "c" : "d" } }',['a','B']);
  230. end;
  231. procedure TTestParser.DoTestObject(S: String; const ElNames: array of String;
  232. DoJSONTest: Boolean);
  233. Var
  234. P : TJSONParser;
  235. J : TJSONData;
  236. O : TJSONObject;
  237. I : Integer;
  238. begin
  239. P:=TJSONParser.Create(S);
  240. Try
  241. J:=P.Parse;
  242. If (J=Nil) then
  243. Fail('Parse of object "'+S+'" fails');
  244. TestJSONType(J,jtObject);
  245. TestItemCount(J,High(ElNames)-Low(ElNames)+1);
  246. O:=TJSONObject(J);
  247. For I:=Low(ElNames) to High(ElNames) do
  248. AssertEquals(Format('Element %d name',[I-Low(Elnames)])
  249. ,ElNames[i], O.Names[I-Low(ElNames)]);
  250. If DoJSONTest then
  251. self.TestJSON(J,S);
  252. Finally
  253. FreeAndNil(J);
  254. FreeAndNil(P);
  255. end;
  256. end;
  257. procedure TTestParser.DoTestArray(S : String; ACount : Integer);
  258. Var
  259. P : TJSONParser;
  260. J : TJSONData;
  261. begin
  262. P:=TJSONParser.Create(S);
  263. Try
  264. J:=P.Parse;
  265. If (J=Nil) then
  266. Fail('Parse of array "'+S+'" fails');
  267. TestJSONType(J,jtArray);
  268. TestItemCount(J,ACount);
  269. TestJSON(J,S);
  270. Finally
  271. FreeAndNil(J);
  272. FreeAndNil(P);
  273. end;
  274. end;
  275. procedure TTestParser.DoTestClass(S: String; AClass: TJSONDataClass);
  276. Var
  277. P : TJSONParser;
  278. D : TJSONData;
  279. begin
  280. P:=TJSONParser.Create(S);
  281. try
  282. D:=P.Parse;
  283. try
  284. AssertEquals('Correct class for '+S+' : ',AClass,D.ClassType);
  285. finally
  286. D.Free
  287. end;
  288. finally
  289. P.Free;
  290. end;
  291. end;
  292. procedure TTestParser.TestErrors;
  293. begin
  294. DoTestError('a');
  295. DoTestError('"b');
  296. DoTestError('1Tru');
  297. DoTestError('b"');
  298. DoTestError('{"a" : }');
  299. DoTestError('{"a" : ""');
  300. DoTestError('{"a : ""');
  301. DoTestError('[1,]');
  302. DoTestError('[,]');
  303. DoTestError('[,,]');
  304. DoTestError('[1,,]');
  305. end;
  306. procedure TTestParser.TestClasses;
  307. begin
  308. SetMyInstanceTypes;
  309. DoTestClass('null',TMyNull);
  310. DoTestClass('true',TMyBoolean);
  311. DoTestClass('1',TMyInteger);
  312. DoTestClass('1.2',TMyFloat);
  313. DoTestClass('123456789012345',TMyInt64);
  314. DoTestClass('"tata"',TMyString);
  315. DoTestClass('{}',TMyObject);
  316. DoTestClass('[]',TMyArray);
  317. end;
  318. procedure TTestParser.CallNoHandler;
  319. begin
  320. GetJSON('1',True).Free;
  321. end;
  322. procedure TTestParser.CallNoHandlerStream;
  323. Var
  324. S : TStringStream;
  325. begin
  326. S:=TstringStream.Create('1');
  327. try
  328. GetJSON(S,True).Free;
  329. finally
  330. S.Free;
  331. end;
  332. end;
  333. procedure TTestParser.TestHandler;
  334. begin
  335. AssertNotNull('Handler installed',GetJSONParserHandler);
  336. end;
  337. procedure TTestParser.TestNoHandlerError;
  338. Var
  339. H : TJSONParserHandler;
  340. begin
  341. H:=GetJSONParserHandler;
  342. try
  343. AssertSame('SetJSONParserHandler returns previous handler',H,SetJSONParserHandler(Nil));
  344. AssertException('No handler raises exception',EJSON,@CallNoHandler);
  345. AssertException('No handler raises exception',EJSON,@CallNoHandlerStream);
  346. finally
  347. SetJSONParserHandler(H);
  348. end;
  349. end;
  350. procedure TTestParser.TestHandlerResult;
  351. Var
  352. D : TJSONData;
  353. begin
  354. D:=GetJSON('"123"');
  355. try
  356. AssertEquals('Have correct string','123',D.AsString);
  357. finally
  358. D.Free;
  359. end;
  360. end;
  361. procedure TTestParser.TestHandlerResultStream;
  362. Var
  363. D : TJSONData;
  364. S : TStream;
  365. begin
  366. S:=TStringStream.Create('"123"');
  367. try
  368. D:=GetJSON(S);
  369. try
  370. AssertEquals('Have correct string','123',D.AsString);
  371. finally
  372. D.Free;
  373. end;
  374. finally
  375. S.Free;
  376. end;
  377. end;
  378. procedure TTestParser.DoTestError(S : String);
  379. Var
  380. P : TJSONParser;
  381. J : TJSONData;
  382. ParseOK : Boolean;
  383. N : String;
  384. begin
  385. ParseOK:=False;
  386. P:=TJSONParser.Create(S);
  387. P.Strict:=True;
  388. J:=Nil;
  389. Try
  390. Try
  391. Repeat
  392. FreeAndNil(J);
  393. J:=P.Parse;
  394. ParseOK:=True;
  395. If (J<>Nil) then
  396. N:=J.ClassName;
  397. Until (J=Nil)
  398. Finally
  399. FreeAndNil(J);
  400. FreeAndNil(P);
  401. end;
  402. except
  403. ParseOk:=False;
  404. end;
  405. If ParseOK then
  406. Fail('Parse of JSON string "'+S+'" should fail, but returned '+N);
  407. end;
  408. procedure TTestParser.DoTestString(S: String);
  409. Var
  410. P : TJSONParser;
  411. J : TJSONData;
  412. begin
  413. P:=TJSONParser.Create('"'+S+'"');
  414. Try
  415. J:=P.Parse;
  416. If (J=Nil) then
  417. Fail('Parse of string "'+S+'" fails');
  418. TestJSONType(J,jtString);
  419. TestAsString(J,JSONStringToString(S));
  420. TestJSON(J,'"'+S+'"');
  421. Finally
  422. FreeAndNil(J);
  423. FreeAndNil(P);
  424. end;
  425. end;
  426. procedure TTestParser.DoTestFloat(F : TJSONFloat);
  427. Var
  428. S : String;
  429. begin
  430. Str(F,S);
  431. DoTestFloat(F,S);
  432. end;
  433. procedure TTestParser.DoTestFloat(F : TJSONFloat; S : String);
  434. Var
  435. P : TJSONParser;
  436. J : TJSONData;
  437. begin
  438. P:=TJSONParser.Create(S);
  439. Try
  440. J:=P.Parse;
  441. If (J=Nil) then
  442. Fail('Parse of float '+S+' fails');
  443. TestJSONType(J,jtNumber);
  444. TestAsFloat(J,F);
  445. Finally
  446. FreeAndNil(J);
  447. FreeAndNil(P);
  448. end;
  449. end;
  450. initialization
  451. RegisterTest(TTestParser);
  452. end.