| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712 |
- (* _ _
- * | |__ _ __ ___ ___ | | __
- * | '_ \| '__/ _ \ / _ \| |/ /
- * | |_) | | | (_) | (_) | <
- * |_.__/|_| \___/ \___/|_|\_\
- *
- * Microframework which helps to develop web Pascal applications.
- *
- * Copyright (c) 2012-2020 Silvio Clecio <[email protected]>
- *
- * Brook framework is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * Brook framework is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Brook framework; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *)
- program Test_MathExpression;
- {$I Tests.inc}
- uses
- SysUtils,
- StrUtils,
- Math,
- Classes,
- libsagui,
- Marshalling,
- Platform,
- BrookUtility,
- BrookLibraryLoader,
- BrookMathExpression,
- Test;
- var
- FakeHandle: Pointer = Pointer(1);
- FakeComponentHandle: TComponent;
- FakeErrType: sg_expr_err_type;
- FakeFlag: Boolean;
- type
- TFakeMathExpression = class(TBrookMathExpression)
- private
- FFakeError: TBrookMathExpressionError;
- public
- constructor Create(AOwner: TComponent); override;
- procedure FakeOnError(Sender: TObject; AError: TBrookMathExpressionError);
- function FakeOnExtension(Sender: TObject;
- AExtension: TBrookMathExpressionExtension): Double;
- procedure FakeOnActivate(Sender: TObject);
- procedure FakeOnDeactivate(Sender: TObject);
- property FakeError: TBrookMathExpressionError read FFakeError;
- end;
- procedure TFakeMathExpression.FakeOnError(Sender: TObject;
- AError: TBrookMathExpressionError);
- begin
- FFakeError := AError;
- end;
- constructor TFakeMathExpression.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- OnExtension := FakeOnExtension;
- OnError := FakeOnError;
- OnActivate := FakeOnActivate;
- OnDeactivate := FakeOnDeactivate;
- FFakeError := Default(TBrookMathExpressionError);
- end;
- {$IFDEF FPC}
- {$PUSH}{$WARN 6058 OFF}
- {$ENDIF}
- function TFakeMathExpression.FakeOnExtension(Sender: TObject;
- AExtension: TBrookMathExpressionExtension): Double;
- begin
- if AExtension.HasArgs then
- case IndexText(AExtension.Ident, ['mysum', 'mymult']) of
- 0: Exit(AExtension.Args[0] + AExtension.Args[1]);
- 1: Exit(AExtension.Args[0] * AExtension.Args[1]);
- end;
- Result := NaN;
- end;
- {$IFDEF FPC}
- {$POP}
- {$ENDIF}
- procedure TFakeMathExpression.FakeOnActivate(Sender: TObject);
- begin
- FakeFlag := True;
- end;
- procedure TFakeMathExpression.FakeOnDeactivate(Sender: TObject);
- begin
- FakeFlag := True;
- end;
- function fake_expr_near(expr: Psg_expr): cint; cdecl;
- begin
- Assert(expr = FakeHandle);
- Result := 123;
- end;
- function fake_expr_err(expr: Psg_expr): sg_expr_err_type; cdecl;
- begin
- Assert(expr = FakeHandle);
- Result := FakeErrType;
- end;
- function fake_expr_strerror(expr: Psg_expr): Pcchar; cdecl;
- var
- M: TMarshaller;
- begin
- Assert(expr = FakeHandle);
- Result := M.ToCString('abc123');
- end;
- function fake_expr_arg(args: Psg_expr_argument; index: cint): cdouble; cdecl;
- begin
- Assert(args = FakeHandle);
- Assert(index = 123);
- Result := 12.34;
- end;
- procedure Test_MathExpressionErrorCreate;
- var
- E: TBrookMathExpressionError;
- begin
- E := TBrookMathExpressionError.Create(FakeHandle);
- Assert(E.Handle = FakeHandle);
- end;
- procedure DoMathExpressionErrorNearLibNotLoaded;
- begin
- TBrookMathExpressionError.Create(FakeHandle).Near;
- end;
- procedure Test_MathExpressionErrorNear;
- var
- E: TBrookMathExpressionError;
- begin
- sg_expr_near := fake_expr_near;
- E := TBrookMathExpressionError.Create(FakeHandle);
- Assert(E.Near = 123);
- TBrookLibraryLoader.Unload;
- try
- AssertExcept(DoMathExpressionErrorNearLibNotLoaded, ESgLibNotLoaded,
- Format(SSgLibNotLoaded, [SG_LIB_NAME]));
- finally
- TBrookLibraryLoader.Load;
- end;
- end;
- procedure DoMathExpressionErrorKindLibNotLoaded;
- begin
- TBrookMathExpressionError.Create(FakeHandle).Kind;
- end;
- procedure Test_MathExpressionErrorKind;
- var
- E: TBrookMathExpressionError;
- begin
- sg_expr_err := fake_expr_err;
- E := TBrookMathExpressionError.Create(FakeHandle);
- FakeErrType := -1;
- Assert(E.Kind = ekNone);
- FakeErrType := SG_EXPR_ERR_UNKNOWN;
- Assert(E.Kind = ekUnknown);
- FakeErrType := SG_EXPR_ERR_UNEXPECTED_NUMBER;
- Assert(E.Kind = ekUnexpectedNumber);
- FakeErrType := SG_EXPR_ERR_UNEXPECTED_WORD;
- Assert(E.Kind = ekUnexpectedWord);
- FakeErrType := SG_EXPR_ERR_UNEXPECTED_PARENS;
- Assert(E.Kind = ekUnexpectedParens);
- FakeErrType := SG_EXPR_ERR_MISSING_OPERAND;
- Assert(E.Kind = ekMissingOperand);
- FakeErrType := SG_EXPR_ERR_UNKNOWN_OPERATOR;
- Assert(E.Kind = ekUnknownOperator);
- FakeErrType := SG_EXPR_ERR_INVALID_FUNC_NAME;
- Assert(E.Kind = ekInvalidFuncName);
- FakeErrType := SG_EXPR_ERR_BAD_PARENS;
- Assert(E.Kind = ekBadParens);
- FakeErrType := SG_EXPR_ERR_TOO_FEW_FUNC_ARGS;
- Assert(E.Kind = ekTooFewFuncArgs);
- FakeErrType := SG_EXPR_ERR_FIRST_ARG_IS_NOT_VAR;
- Assert(E.Kind = ekFirstArgIsNotVar);
- FakeErrType := SG_EXPR_ERR_BAD_VARIABLE_NAME;
- Assert(E.Kind = ekBadVariableName);
- FakeErrType := SG_EXPR_ERR_BAD_ASSIGNMENT;
- Assert(E.Kind = ekBadAssignment);
- TBrookLibraryLoader.Unload;
- try
- AssertExcept(DoMathExpressionErrorKindLibNotLoaded, ESgLibNotLoaded,
- Format(SSgLibNotLoaded, [SG_LIB_NAME]));
- finally
- TBrookLibraryLoader.Load;
- end;
- end;
- procedure DoMathExpressionErrorMessageLibNotLoaded;
- begin
- TBrookMathExpressionError.Create(FakeHandle).Message;
- end;
- procedure Test_MathExpressionErrorMessage;
- var
- E: TBrookMathExpressionError;
- begin
- sg_expr_strerror := fake_expr_strerror;
- E := TBrookMathExpressionError.Create(FakeHandle);
- Assert(E.Message = 'abc123');
- TBrookLibraryLoader.Unload;
- try
- AssertExcept(DoMathExpressionErrorMessageLibNotLoaded, ESgLibNotLoaded,
- Format(SSgLibNotLoaded, [SG_LIB_NAME]));
- finally
- TBrookLibraryLoader.Load;
- end;
- end;
- procedure Test_MathExpressionErrorHandle;
- var
- E1, E2: TBrookMathExpressionError;
- begin
- E1 := TBrookMathExpressionError.Create(nil);
- E2 := TBrookMathExpressionError.Create(FakeHandle);
- Assert(not Assigned(E1.Handle));
- Assert(Assigned(E2.Handle));
- Assert(E2.Handle = FakeHandle);
- end;
- procedure Test_MathExpressionExtensionCreate;
- var
- E1, E2: TBrookMathExpressionExtension;
- begin
- E1 := TBrookMathExpressionExtension.Create(nil, '');
- E2 := TBrookMathExpressionExtension.Create(FakeHandle, 'abc123');
- Assert(E1.Ident = '');
- Assert(not Assigned(E1.Handle));
- Assert(E2.Ident = 'abc123');
- Assert(Assigned(E2.Handle));
- end;
- procedure Test_MathExpressionExtensionHasArgs;
- var
- E1, E2: TBrookMathExpressionExtension;
- begin
- E1 := TBrookMathExpressionExtension.Create(nil, '');
- E2 := TBrookMathExpressionExtension.Create(FakeHandle, 'abc123');
- Assert(not E1.HasArgs);
- Assert(E2.HasArgs);
- end;
- procedure DoMathExpressionErrorArgsLibNotLoaded;
- begin
- TBrookMathExpressionExtension.Create(FakeHandle, 'abc123').Args[0];
- end;
- procedure Test_MathExpressionExtensionArgs;
- var
- E1, E2: TBrookMathExpressionExtension;
- begin
- E1 := TBrookMathExpressionExtension.Create(nil, '');
- E2 := TBrookMathExpressionExtension.Create(FakeHandle, 'abc123');
- sg_expr_arg := fake_expr_arg;
- Assert(E1.Args[0].ToString = NaN.ToString);
- Assert(E1[0].ToString = NaN.ToString);
- Assert(E2.Args[123].ToString = Double(12.34).ToString);
- Assert(E2[123].ToString = Double(12.34).ToString);
- TBrookLibraryLoader.Unload;
- try
- AssertExcept(DoMathExpressionErrorArgsLibNotLoaded, ESgLibNotLoaded,
- Format(SSgLibNotLoaded, [SG_LIB_NAME]));
- finally
- TBrookLibraryLoader.Load;
- end;
- end;
- procedure Test_MathExpressionExtensionIdent;
- var
- E1, E2: TBrookMathExpressionExtension;
- begin
- E1 := TBrookMathExpressionExtension.Create(nil, '');
- E2 := TBrookMathExpressionExtension.Create(FakeHandle, 'abc123');
- Assert(E1.Ident = '');
- Assert(not Assigned(E1.Handle));
- Assert(E2.Ident = 'abc123');
- end;
- procedure Test_MathExpressionExtensionHandle;
- var
- E1, E2: TBrookMathExpressionExtension;
- begin
- E1 := TBrookMathExpressionExtension.Create(nil, '');
- E2 := TBrookMathExpressionExtension.Create(FakeHandle, 'abc123');
- Assert(not Assigned(E1.Handle));
- Assert(Assigned(E2.Handle));
- Assert(E2.Handle = FakeHandle);
- end;
- procedure Test_MathExpressionCreate;
- var
- E1, E2: TBrookMathExpression;
- begin
- FakeComponentHandle := TComponent.Create(nil);
- E1 := TBrookMathExpression.Create(nil);
- E2 := TBrookMathExpression.Create(FakeComponentHandle);
- try
- Assert(not Assigned(E1.Owner));
- Assert(Assigned(E2.Owner));
- Assert(E2.Owner = FakeComponentHandle);
- Assert(Assigned(E1.Extensions));
- E1.Active := True;
- Assert(E1.Active);
- TBrookLibraryLoader.Unload;
- try
- Assert(not E1.Active);
- finally
- TBrookLibraryLoader.Load;
- end;
- finally
- E1.Destroy;
- E2.Destroy;
- FakeComponentHandle.Free;
- end;
- end;
- procedure Test_MathExpressionOpen;
- var
- E: TBrookMathExpression;
- begin
- E := TBrookMathExpression.Create(nil);
- try
- Assert(not E.Active);
- E.Open;
- Assert(E.Active);
- finally
- E.Free;
- end;
- end;
- procedure Test_MathExpressionClose;
- var
- E: TBrookMathExpression;
- begin
- E := TBrookMathExpression.Create(nil);
- try
- Assert(not E.Active);
- E.Open;
- Assert(E.Active);
- E.Close;
- Assert(not E.Active);
- finally
- E.Free;
- end;
- end;
- procedure DoMathExpressionCompileInactiveMathExpression(
- const AArgs: array of const);
- var
- E: TBrookMathExpressionError;
- begin
- TBrookMathExpression(AArgs[0].VObject).Compile('1+2', E);
- end;
- procedure Test_MathExpressionCompile;
- var
- M1: TBrookMathExpression;
- M2: TFakeMathExpression;
- E: TBrookMathExpressionError;
- begin
- M1 := TBrookMathExpression.Create(nil);
- try
- Assert(not M1.Compiled);
- M1.Open;
- Assert(M1.Compile('1+2', E));
- Assert(M1.Compile('(1+2', E));
- M1.Clear;
- Assert(not M1.Compile('(1+2', E));
- Assert(E.Near = 4);
- Assert(E.Message.Trim = 'Bad parenthesis.');
- Assert(E.Kind = ekBadParens);
- Assert(not M1.Compile('1++2', E));
- Assert(E.Near = 2);
- Assert(E.Message.Trim = 'Missing expected operand.');
- Assert(E.Kind = ekMissingOperand);
- M1.Close;
- AssertExcept(DoMathExpressionCompileInactiveMathExpression,
- EInvalidOpException, SBrookInactiveMathExpression, [M1]);
- M1.Open;
- TBrookLibraryLoader.Unload;
- try
- AssertExcept(DoMathExpressionCompileInactiveMathExpression,
- EInvalidOpException, SBrookInactiveMathExpression, [M1]);
- finally
- TBrookLibraryLoader.Load;
- end;
- finally
- M1.Free;
- end;
- M2 := TFakeMathExpression.Create(nil);
- try
- M2.Open;
- Assert(not M2.Compile('(1+2'));
- Assert(M2.FakeError.Near = 4);
- Assert(M2.FakeError.Message.Trim = 'Bad parenthesis.');
- Assert(M2.FakeError.Kind = ekBadParens);
- Assert(not M2.Compile('1++2'));
- Assert(M2.FakeError.Near = 2);
- Assert(M2.FakeError.Message.Trim = 'Missing expected operand.');
- Assert(M2.FakeError.Kind = ekMissingOperand);
- finally
- M2.Free;
- end;
- end;
- procedure Test_MathExpressionClear;
- var
- M: TBrookMathExpression;
- begin
- M := TBrookMathExpression.Create(nil);
- try
- M.Open;
- M.Compile('1+2');
- Assert(M.Compiled);
- M.Clear;
- Assert(not M.Compiled);
- M.Clear;
- M.Clear;
- finally
- M.Free;
- end;
- end;
- procedure Test_MathExpressionEvaluate;
- var
- M: TBrookMathExpression;
- begin
- M := TBrookMathExpression.Create(nil);
- try
- M.Open;
- Assert(not M.Compiled);
- M.Expression := '1.2+3.4';
- Assert(M.Evaluate.ToString = Double(4.6).ToString);
- Assert(M.Compiled);
- Assert(M.Evaluate.ToString = Double(4.6).ToString);
- finally
- M.Free;
- end;
- end;
- procedure DoMathExpressionGetVariableInactiveMathExpression(
- const AArgs: array of const);
- begin
- TBrookMathExpression(AArgs[0].VObject).GetVariable('foo');
- end;
- procedure Test_MathExpressionGetVariable;
- var
- M: TBrookMathExpression;
- begin
- M := TBrookMathExpression.Create(nil);
- try
- M.Open;
- Assert(M.GetVariable('foo').ToString = Double(0).ToString);
- M.SetVariable('foo', 12.34);
- Assert(M.GetVariable('foo').ToString = Double(12.34).ToString);
- M.Expression := 'foo=56.78';
- M.Evaluate;
- Assert(M.GetVariable('foo').ToString = Double(56.78).ToString);
- M.Close;
- AssertExcept(DoMathExpressionGetVariableInactiveMathExpression,
- EInvalidOpException, SBrookInactiveMathExpression, [M]);
- finally
- M.Free;
- end;
- end;
- procedure DoMathExpressionSetVariableInactiveMathExpression(
- const AArgs: array of const);
- begin
- TBrookMathExpression(AArgs[0].VObject).SetVariable('foo', 12.34);
- end;
- procedure Test_MathExpressionSetVariable;
- var
- M: TBrookMathExpression;
- begin
- M := TBrookMathExpression.Create(nil);
- try
- M.Open;
- M.Expression := 'foo+56.78';
- Assert(M.GetVariable('foo').ToString = Double(0).ToString);
- M.SetVariable('foo', 12.34);
- Assert(M.GetVariable('foo').ToString = Double(12.34).ToString);
- Assert(M.Evaluate.ToString = Double(69.12).ToString);
- M.Close;
- AssertExcept(DoMathExpressionSetVariableInactiveMathExpression,
- EInvalidOpException, SBrookInactiveMathExpression, [M]);
- finally
- M.Free;
- end;
- end;
- procedure Test_MathExpressionCompiled;
- var
- M: TBrookMathExpression;
- begin
- M := TBrookMathExpression.Create(nil);
- try
- M.Open;
- Assert(not M.Compiled);
- M.Compile('1+2');
- Assert(M.Compiled);
- M.Close;
- Assert(not M.Compiled);
- finally
- M.Free;
- end;
- end;
- procedure Test_MathExpressionVariables;
- var
- M: TBrookMathExpression;
- begin
- M := TBrookMathExpression.Create(nil);
- try
- M.Open;
- M.Expression := 'foo+bar';
- M.Variables['foo'] := 12.34;
- M['bar'] := 56.78;
- Assert(M.Evaluate.ToString = Double(69.12).ToString);
- finally
- M.Free;
- end;
- end;
- procedure Test_MathExpressionActive;
- var
- M: TBrookMathExpression;
- begin
- M := TBrookMathExpression.Create(nil);
- try
- Assert(not M.Active);
- M.Active := not M.Active;
- Assert(M.Active);
- M.Active := True;
- Assert(M.Active);
- finally
- M.Free;
- end;
- end;
- procedure Test_MathExpressionExpression;
- var
- M: TBrookMathExpression;
- begin
- M := TBrookMathExpression.Create(nil);
- try
- M.Open;
- Assert(M.Expression.IsEmpty);
- M.Expression := '1.2+3.4';
- Assert(M.Expression = '1.2+3.4');
- Assert(M.Evaluate.ToString = Double(4.6).ToString);
- Assert(M.Compiled);
- M.Expression := '1+2';
- Assert(not M.Compiled);
- finally
- M.Free;
- end;
- end;
- procedure Test_MathExpressionExtensions;
- var
- M: TFakeMathExpression;
- begin
- M := TFakeMathExpression.Create(nil);
- try
- M.Open;
- Assert(Assigned(M.Extensions));
- M.Expression := 'mysum(1.2, 3.4) + mymult(5.6, 7.8)';
- Assert(M.Evaluate.ToString = NaN.ToString);
- M.Extensions.AddStrings(['mysum', 'mymult']);
- Assert(M.Evaluate.ToString = Double(48.28).ToString);
- finally
- M.Free;
- end;
- end;
- procedure Test_MathExpressionOnExtension;
- begin
- Test_MathExpressionExtensions;
- end;
- procedure Test_MathExpressionOnError;
- var
- M: TFakeMathExpression;
- begin
- M := TFakeMathExpression.Create(nil);
- try
- M.Open;
- Assert(not M.Compile('(1+2'));
- Assert(M.FakeError.Near = 4);
- Assert(M.FakeError.Message.Trim = 'Bad parenthesis.');
- Assert(M.FakeError.Kind = ekBadParens);
- Assert(not M.Compile('1++2'));
- Assert(M.FakeError.Near = 2);
- Assert(M.FakeError.Message.Trim = 'Missing expected operand.');
- Assert(M.FakeError.Kind = ekMissingOperand);
- finally
- M.Free;
- end;
- end;
- procedure Test_MathExpressionOnActivate;
- var
- M: TFakeMathExpression;
- begin
- M := TFakeMathExpression.Create(nil);
- try
- M.OnActivate := M.FakeOnActivate;
- FakeFlag := False;
- M.Open;
- Assert(FakeFlag);
- finally
- M.Free;
- end;
- end;
- procedure Test_MathExpressionOnDeactivate;
- var
- M: TFakeMathExpression;
- begin
- M := TFakeMathExpression.Create(nil);
- try
- M.Open;
- M.OnDeactivate := M.FakeOnDeactivate;
- FakeFlag := False;
- M.Close;
- Assert(FakeFlag);
- finally
- M.Free;
- end;
- end;
- procedure Test_MathExpression_Evaluate;
- begin
- Assert(Evaluate('').ToString = NaN.ToString);
- Assert(Evaluate('1.2+3.4').ToString = Double(4.6).ToString);
- Assert(Evaluate('foo=9.8, bar=7.6, foo + bar').ToString = Double(17.4).ToString);
- end;
- begin
- {$IF (NOT DEFINED(FPC)) AND DEFINED(DEBUG)}
- ReportMemoryLeaksOnShutdown := True;
- {$ENDIF}
- TBrookLibraryLoader.Load;
- try
- Test_MathExpressionErrorCreate;
- Test_MathExpressionErrorNear;
- Test_MathExpressionErrorKind;
- Test_MathExpressionErrorMessage;
- Test_MathExpressionErrorHandle;
- Test_MathExpressionExtensionCreate;
- Test_MathExpressionExtensionHasArgs;
- Test_MathExpressionExtensionArgs;
- Test_MathExpressionExtensionIdent;
- Test_MathExpressionExtensionHandle;
- Test_MathExpressionCreate;
- // Test_MathExpressionDestroy - not required
- Test_MathExpressionOpen;
- Test_MathExpressionClose;
- Test_MathExpressionCompile;
- Test_MathExpressionClear;
- Test_MathExpressionEvaluate;
- Test_MathExpressionGetVariable;
- Test_MathExpressionSetVariable;
- Test_MathExpressionCompiled;
- Test_MathExpressionVariables;
- Test_MathExpressionActive;
- Test_MathExpressionExpression;
- Test_MathExpressionExtensions;
- Test_MathExpressionOnExtension;
- Test_MathExpressionOnError;
- Test_MathExpressionOnActivate;
- Test_MathExpressionOnDeactivate;
- Test_MathExpression_Evaluate;
- finally
- TBrookLibraryLoader.Unload;
- end;
- end.
|