testjsonparser.pp 11 KB

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