utcexprparsaggr.pp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. unit utcExprParsAggr;
  2. {$mode objfpc}
  3. {$h+}
  4. interface
  5. uses
  6. Classes, SysUtils, math, punit, fpexprpars;
  7. procedure RegisterTests(aTop : PSuite);
  8. implementation
  9. uses typinfo;
  10. type
  11. TAggregateNode = Class(TFPExprNode)
  12. Public
  13. InitCount : Integer;
  14. UpdateCount : Integer;
  15. Class Function IsAggregate: Boolean; override;
  16. Function NodeType: TResultType; override;
  17. Procedure InitAggregate; override;
  18. Procedure UpdateAggregate; override;
  19. procedure GetNodeValue(var Result: TFPExpressionResult); override;
  20. end;
  21. TVarCallback = class
  22. procedure GetVar(var Result: TFPExpressionResult; constref AName: ShortString);
  23. end;
  24. var
  25. VarCallBack : TVarCallback;
  26. FVarValue : Integer;
  27. FLeft : TAggregateNode;
  28. FRight : TAggregateNode;
  29. FFunction : TFPExprIdentifierDef;
  30. FFunction2 : TFPExprIdentifierDef;
  31. procedure TVarCallback.GetVar(var Result: TFPExpressionResult; constref AName: ShortString);
  32. begin
  33. Result.ResultType:=FFunction2.ResultType;
  34. Case Result.ResultType of
  35. rtInteger : Result.ResInteger:=FVarValue;
  36. rtFloat : Result.ResFloat:=FVarValue / 2;
  37. rtCurrency : Result.ResCurrency:=FVarValue / 2;
  38. end;
  39. end;
  40. procedure AssertEquals(Msg: String; AExpected, AActual: TResultType); overload;
  41. begin
  42. AssertEquals(Msg, ResultTypeName(AExpected), ResultTypeName(AActual));
  43. end;
  44. function SuiteSetup: TTestString;
  45. begin
  46. Result := '';
  47. FVarValue:=0;
  48. VarCallBack:=TVarCallback.Create;
  49. FFunction:=TFPExprIdentifierDef.Create(Nil);
  50. FFunction.Name:='Count';
  51. FFunction2:=TFPExprIdentifierDef.Create(Nil);
  52. FFunction2.Name:='MyVar';
  53. FFunction2.ResultType:=rtInteger;
  54. FFunction2.IdentifierType:=itVariable;
  55. FFunction2.OnGetVariableValue:[email protected];
  56. FLeft:=TAggregateNode.Create;
  57. FRight:=TAggregateNode.Create;
  58. end;
  59. function SuiteTearDown: TTestString;
  60. begin
  61. Result := '';
  62. FreeAndNil(VarCallBack);
  63. FreeAndNil(FFunction);
  64. FreeAndNil(FFunction2);
  65. FreeAndNil(FLeft);
  66. FreeAndNil(FRight);
  67. end;
  68. function TestParserAggregate_TestIsAggregate: TTestString;
  69. begin
  70. Result:='';
  71. AssertEquals('ExprNode',False,TFPExprNode.IsAggregate);
  72. AssertEquals('TAggregateExpr',True,TAggregateExpr.IsAggregate);
  73. AssertEquals('TAggregateExpr',False,TFPBinaryOperation.IsAggregate);
  74. end;
  75. function TestParserAggregate_TestHasAggregate: TTestString;
  76. Var
  77. N : TFPExprNode;
  78. begin
  79. Result:='';
  80. N:=TFPExprNode.Create;
  81. try
  82. AssertEquals('ExprNode',False,N.HasAggregate);
  83. finally
  84. N.Free;
  85. end;
  86. N:=TAggregateExpr.Create;
  87. try
  88. AssertEquals('TAggregateExpr',True,N.HasAggregate);
  89. finally
  90. N.Free;
  91. end;
  92. end;
  93. function TestParserAggregate_TestBinaryAggregate: TTestString;
  94. Var
  95. B : TFPBinaryOperation;
  96. begin
  97. Result:='';
  98. B:=TFPBinaryOperation.Create(Fleft,TFPConstExpression.CreateInteger(1));
  99. try
  100. FLeft:=Nil;
  101. AssertEquals('Binary',True,B.HasAggregate);
  102. finally
  103. B.Free;
  104. FLeft:=TAggregateNode.Create; // Recreate for next test
  105. end;
  106. B:=TFPBinaryOperation.Create(TFPConstExpression.CreateInteger(1),FRight);
  107. try
  108. FRight:=Nil;
  109. AssertEquals('Binary',True,B.HasAggregate);
  110. finally
  111. B.Free;
  112. FRight:=TAggregateNode.Create; // Recreate for next test
  113. end;
  114. end;
  115. function TestParserAggregate_TestUnaryAggregate: TTestString;
  116. Var
  117. B : TFPUnaryOperator;
  118. begin
  119. Result:='';
  120. B:=TFPUnaryOperator.Create(Fleft);
  121. try
  122. FLeft:=Nil;
  123. AssertEquals('Unary',True,B.HasAggregate);
  124. finally
  125. B.Free;
  126. FLeft:=TAggregateNode.Create; // Recreate for next test
  127. end;
  128. end;
  129. function TestParserAggregate_TestCountAggregate: TTestString;
  130. Var
  131. C : TAggregateCount;
  132. I : Integer;
  133. R : TFPExpressionResult;
  134. begin
  135. Result:='';
  136. FFunction.ResultType:=rtInteger;
  137. FFunction.ParameterTypes:='';
  138. C:=TAggregateCount.CreateFunction(FFunction,Nil);
  139. try
  140. C.Check;
  141. C.InitAggregate;
  142. For I:=1 to 11 do
  143. C.UpdateAggregate;
  144. C.GetNodeValue(R);
  145. AssertEquals('Correct type',rtInteger,R.ResultType);
  146. AssertEquals('Correct value',11,R.ResInteger);
  147. finally
  148. C.Free;
  149. end;
  150. end;
  151. function TestParserAggregate_TestSumAggregate: TTestString;
  152. Var
  153. C : TAggregateSum;
  154. V : TFPExprVariable;
  155. I : Integer;
  156. R : TFPExpressionResult;
  157. A : TExprArgumentArray;
  158. begin
  159. Result:='';
  160. FFunction.ResultType:=rtInteger;
  161. FFunction.ParameterTypes:='I';
  162. FFunction.Name:='SUM';
  163. FFunction2.ResultType:=rtInteger;
  164. C:=Nil;
  165. V:=TFPExprVariable.CreateIdentifier(FFunction2);
  166. try
  167. SetLength(A,1);
  168. A[0]:=V;
  169. C:=TAggregateSum.CreateFunction(FFunction,A);
  170. C.Check;
  171. C.InitAggregate;
  172. For I:=1 to 10 do
  173. begin
  174. FVarValue:=I;
  175. C.UpdateAggregate;
  176. end;
  177. C.GetNodeValue(R);
  178. AssertEquals('Correct type',rtInteger,R.ResultType);
  179. AssertEquals('Correct value',55,R.ResInteger);
  180. finally
  181. C.Free;
  182. end;
  183. end;
  184. function TestParserAggregate_TestSumAggregate2: TTestString;
  185. Var
  186. C : TAggregateSum;
  187. V : TFPExprVariable;
  188. I : Integer;
  189. R : TFPExpressionResult;
  190. A : TExprArgumentArray;
  191. begin
  192. Result:='';
  193. FFunction.ResultType:=rtFloat;
  194. FFunction.ParameterTypes:='F';
  195. FFunction.Name:='SUM';
  196. FFunction2.ResultType:=rtFloat;
  197. C:=Nil;
  198. V:=TFPExprVariable.CreateIdentifier(FFunction2);
  199. try
  200. SetLength(A,1);
  201. A[0]:=V;
  202. C:=TAggregateSum.CreateFunction(FFunction,A);
  203. C.Check;
  204. C.InitAggregate;
  205. For I:=1 to 10 do
  206. begin
  207. FVarValue:=I;
  208. C.UpdateAggregate;
  209. end;
  210. C.GetNodeValue(R);
  211. AssertEquals('Correct type',rtFloat,R.ResultType);
  212. AssertEquals('Correct value',55/2,R.ResFloat,0.1);
  213. finally
  214. C.Free;
  215. end;
  216. end;
  217. function TestParserAggregate_TestSumAggregate3: TTestString;
  218. Var
  219. C : TAggregateSum;
  220. V : TFPExprVariable;
  221. I : Integer;
  222. R : TFPExpressionResult;
  223. A : TExprArgumentArray;
  224. begin
  225. Result:='';
  226. FFunction.ResultType:=rtCurrency;
  227. FFunction.ParameterTypes:='F';
  228. FFunction.Name:='SUM';
  229. FFunction2.ResultType:=rtCurrency;
  230. C:=Nil;
  231. V:=TFPExprVariable.CreateIdentifier(FFunction2);
  232. try
  233. SetLength(A,1);
  234. A[0]:=V;
  235. C:=TAggregateSum.CreateFunction(FFunction,A);
  236. C.Check;
  237. C.InitAggregate;
  238. For I:=1 to 10 do
  239. begin
  240. FVarValue:=I;
  241. C.UpdateAggregate;
  242. end;
  243. C.GetNodeValue(R);
  244. AssertEquals('Correct type',rtCurrency,R.ResultType);
  245. AssertEquals('Correct value',55/2,R.ResCurrency,0.1);
  246. finally
  247. C.Free;
  248. end;
  249. end;
  250. function TestParserAggregate_TestAvgAggregate: TTestString;
  251. Var
  252. C : TAggregateAvg;
  253. V : TFPExprVariable;
  254. I : Integer;
  255. R : TFPExpressionResult;
  256. A : TExprArgumentArray;
  257. begin
  258. Result:='';
  259. FFunction.ResultType:=rtInteger;
  260. FFunction.ParameterTypes:='F';
  261. FFunction.Name:='AVG';
  262. FFunction2.ResultType:=rtInteger;
  263. C:=Nil;
  264. V:=TFPExprVariable.CreateIdentifier(FFunction2);
  265. try
  266. SetLength(A,1);
  267. A[0]:=V;
  268. C:=TAggregateAvg.CreateFunction(FFunction,A);
  269. C.Check;
  270. C.InitAggregate;
  271. For I:=1 to 10 do
  272. begin
  273. FVarValue:=I;
  274. C.UpdateAggregate;
  275. end;
  276. C.GetNodeValue(R);
  277. AssertEquals('Correct type',rtFloat,R.ResultType);
  278. AssertEquals('Correct value',5.5,R.ResFloat,0.1);
  279. finally
  280. C.Free;
  281. end;
  282. end;
  283. function TestParserAggregate_TestAvgAggregate2: TTestString;
  284. Var
  285. C : TAggregateAvg;
  286. V : TFPExprVariable;
  287. I : Integer;
  288. R : TFPExpressionResult;
  289. A : TExprArgumentArray;
  290. begin
  291. Result:='';
  292. FFunction.ResultType:=rtInteger;
  293. FFunction.ParameterTypes:='F';
  294. FFunction.Name:='AVG';
  295. FFunction2.ResultType:=rtFloat;
  296. C:=Nil;
  297. V:=TFPExprVariable.CreateIdentifier(FFunction2);
  298. try
  299. SetLength(A,1);
  300. A[0]:=V;
  301. C:=TAggregateAvg.CreateFunction(FFunction,A);
  302. C.Check;
  303. C.InitAggregate;
  304. For I:=1 to 10 do
  305. begin
  306. FVarValue:=I;
  307. C.UpdateAggregate;
  308. end;
  309. C.GetNodeValue(R);
  310. AssertEquals('Correct type',rtFloat,R.ResultType);
  311. AssertEquals('Correct value',5.5/2,R.ResFloat,0.1);
  312. finally
  313. C.Free;
  314. end;
  315. end;
  316. function TestParserAggregate_TestAvgAggregate3: TTestString;
  317. Var
  318. C : TAggregateAvg;
  319. V : TFPExprVariable;
  320. R : TFPExpressionResult;
  321. A : TExprArgumentArray;
  322. begin
  323. Result:='';
  324. FFunction.ResultType:=rtInteger;
  325. FFunction.ParameterTypes:='F';
  326. FFunction.Name:='AVG';
  327. FFunction2.ResultType:=rtFloat;
  328. C:=Nil;
  329. V:=TFPExprVariable.CreateIdentifier(FFunction2);
  330. try
  331. SetLength(A,1);
  332. A[0]:=V;
  333. C:=TAggregateAvg.CreateFunction(FFunction,A);
  334. C.Check;
  335. C.InitAggregate;
  336. C.GetNodeValue(R);
  337. AssertEquals('Correct type',rtFloat,R.ResultType);
  338. AssertEquals('Correct value',0.0,R.ResFloat,0.1);
  339. finally
  340. C.Free;
  341. end;
  342. end;
  343. { TAggregateNode }
  344. class function TAggregateNode.IsAggregate: Boolean;
  345. begin
  346. Result:=True
  347. end;
  348. function TAggregateNode.NodeType: TResultType;
  349. begin
  350. Result:=rtInteger;
  351. end;
  352. procedure TAggregateNode.InitAggregate;
  353. begin
  354. inherited InitAggregate;
  355. inc(InitCount)
  356. end;
  357. procedure TAggregateNode.UpdateAggregate;
  358. begin
  359. inherited UpdateAggregate;
  360. inc(UpdateCount);
  361. end;
  362. procedure TAggregateNode.GetNodeValue(var Result: TFPExpressionResult);
  363. begin
  364. Result.ResultType:=rtInteger;
  365. Result.ResInteger:=updateCount;
  366. end;
  367. procedure RegisterTests(aTop: PSuite);
  368. var
  369. lSuite : PSuite;
  370. begin
  371. lSuite:=AddSuite('TParserAggregateTests', @SuiteSetup, @SuiteTearDown, aTop);
  372. AddTest('TestIsAggregate', @TestParserAggregate_TestIsAggregate, lSuite);
  373. AddTest('TestHasAggregate', @TestParserAggregate_TestHasAggregate, lSuite);
  374. AddTest('TestBinaryAggregate', @TestParserAggregate_TestBinaryAggregate, lSuite);
  375. AddTest('TestUnaryAggregate', @TestParserAggregate_TestUnaryAggregate, lSuite);
  376. AddTest('TestCountAggregate', @TestParserAggregate_TestCountAggregate, lSuite);
  377. AddTest('TestSumAggregate', @TestParserAggregate_TestSumAggregate, lSuite);
  378. AddTest('TestSumAggregate2', @TestParserAggregate_TestSumAggregate2, lSuite);
  379. AddTest('TestSumAggregate3', @TestParserAggregate_TestSumAggregate3, lSuite);
  380. AddTest('TestAvgAggregate', @TestParserAggregate_TestAvgAggregate, lSuite);
  381. AddTest('TestAvgAggregate2', @TestParserAggregate_TestAvgAggregate2, lSuite);
  382. AddTest('TestAvgAggregate3', @TestParserAggregate_TestAvgAggregate3, lSuite);
  383. end;
  384. end.