testjsonparser.pp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  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. {
  295. DoTestError('a');
  296. DoTestError('"b');
  297. DoTestError('1Tru');
  298. }
  299. DoTestError('b"');
  300. DoTestError('{"a" : }');
  301. DoTestError('{"a" : ""');
  302. DoTestError('{"a : ""');
  303. {
  304. DoTestError('[1,]');
  305. DoTestError('[,]');
  306. DoTestError('[,,]');
  307. DoTestError('[1,,]');
  308. }
  309. end;
  310. procedure TTestParser.TestClasses;
  311. begin
  312. SetMyInstanceTypes;
  313. DoTestClass('null',TMyNull);
  314. DoTestClass('true',TMyBoolean);
  315. DoTestClass('1',TMyInteger);
  316. DoTestClass('1.2',TMyFloat);
  317. DoTestClass('123456789012345',TMyInt64);
  318. DoTestClass('"tata"',TMyString);
  319. DoTestClass('{}',TMyObject);
  320. DoTestClass('[]',TMyArray);
  321. end;
  322. procedure TTestParser.CallNoHandler;
  323. begin
  324. GetJSON('1',True).Free;
  325. end;
  326. procedure TTestParser.CallNoHandlerStream;
  327. Var
  328. S : TStringStream;
  329. begin
  330. S:=TstringStream.Create('1');
  331. try
  332. GetJSON(S,True).Free;
  333. finally
  334. S.Free;
  335. end;
  336. end;
  337. procedure TTestParser.TestHandler;
  338. begin
  339. AssertNotNull('Handler installed',GetJSONParserHandler);
  340. end;
  341. procedure TTestParser.TestNoHandlerError;
  342. Var
  343. H : TJSONParserHandler;
  344. begin
  345. H:=GetJSONParserHandler;
  346. try
  347. AssertSame('SetJSONParserHandler returns previous handler',H,SetJSONParserHandler(Nil));
  348. AssertException('No handler raises exception',EJSON,@CallNoHandler);
  349. AssertException('No handler raises exception',EJSON,@CallNoHandlerStream);
  350. finally
  351. SetJSONParserHandler(H);
  352. end;
  353. end;
  354. procedure TTestParser.TestHandlerResult;
  355. Var
  356. D : TJSONData;
  357. begin
  358. D:=GetJSON('"123"');
  359. try
  360. AssertEquals('Have correct string','123',D.AsString);
  361. finally
  362. D.Free;
  363. end;
  364. end;
  365. procedure TTestParser.TestHandlerResultStream;
  366. Var
  367. D : TJSONData;
  368. S : TStream;
  369. begin
  370. S:=TStringStream.Create('"123"');
  371. try
  372. D:=GetJSON(S);
  373. try
  374. AssertEquals('Have correct string','123',D.AsString);
  375. finally
  376. D.Free;
  377. end;
  378. finally
  379. S.Free;
  380. end;
  381. end;
  382. procedure TTestParser.DoTestError(S : String);
  383. Var
  384. P : TJSONParser;
  385. J : TJSONData;
  386. ParseOK : Boolean;
  387. N : String;
  388. begin
  389. ParseOK:=False;
  390. P:=TJSONParser.Create(S);
  391. P.Strict:=True;
  392. J:=Nil;
  393. Try
  394. Try
  395. Repeat
  396. FreeAndNil(J);
  397. J:=P.Parse;
  398. ParseOK:=True;
  399. If (J<>Nil) then
  400. N:=J.ClassName;
  401. Until (J=Nil)
  402. Finally
  403. FreeAndNil(J);
  404. FreeAndNil(P);
  405. end;
  406. except
  407. ParseOk:=False;
  408. end;
  409. If ParseOK then
  410. Fail('Parse of JSON string "'+S+'" should fail, but returned '+N);
  411. end;
  412. procedure TTestParser.DoTestString(S: String);
  413. Var
  414. P : TJSONParser;
  415. J : TJSONData;
  416. begin
  417. P:=TJSONParser.Create('"'+S+'"');
  418. Try
  419. J:=P.Parse;
  420. If (J=Nil) then
  421. Fail('Parse of string "'+S+'" fails');
  422. TestJSONType(J,jtString);
  423. TestAsString(J,JSONStringToString(S));
  424. TestJSON(J,'"'+S+'"');
  425. Finally
  426. FreeAndNil(J);
  427. FreeAndNil(P);
  428. end;
  429. end;
  430. procedure TTestParser.DoTestFloat(F : TJSONFloat);
  431. Var
  432. S : String;
  433. begin
  434. Str(F,S);
  435. DoTestFloat(F,S);
  436. end;
  437. procedure TTestParser.DoTestFloat(F : TJSONFloat; S : String);
  438. Var
  439. P : TJSONParser;
  440. J : TJSONData;
  441. begin
  442. P:=TJSONParser.Create(S);
  443. Try
  444. J:=P.Parse;
  445. If (J=Nil) then
  446. Fail('Parse of float '+S+' fails');
  447. TestJSONType(J,jtNumber);
  448. TestAsFloat(J,F);
  449. Finally
  450. FreeAndNil(J);
  451. FreeAndNil(P);
  452. end;
  453. end;
  454. initialization
  455. RegisterTest(TTestParser);
  456. end.