From a51a7db4a098f1a3cb52261262c7df30a070d878 Mon Sep 17 00:00:00 2001 From: Mario Lukas Mauberger Date: Sun, 19 Feb 2023 15:07:18 +0100 Subject: [PATCH] CATTY-699 Port FormulaParserTests to Swift --- src/Catty.xcodeproj/project.pbxproj | 28 +- .../Formula/FormulaParserErrorDetectionTest.m | 166 ------ .../FormulaParserErrorDetectionTest.swift | 90 ++++ .../Formula/FormulaParserFunctionsTest.m | 362 ------------- .../Formula/FormulaParserFunctionsTest.swift | 219 ++++++++ .../Formula/FormulaParserOperatorsTest.m | 500 ------------------ .../Formula/FormulaParserOperatorsTest.swift | 459 ++++++++++++++++ .../Formula/FormulaParserTest.swift | 92 ++-- .../Formula/FormulaTestHelper.swift | 112 ++++ 9 files changed, 931 insertions(+), 1097 deletions(-) delete mode 100644 src/CattyTests/Formula/FormulaParserErrorDetectionTest.m create mode 100644 src/CattyTests/Formula/FormulaParserErrorDetectionTest.swift delete mode 100644 src/CattyTests/Formula/FormulaParserFunctionsTest.m create mode 100644 src/CattyTests/Formula/FormulaParserFunctionsTest.swift delete mode 100644 src/CattyTests/Formula/FormulaParserOperatorsTest.m create mode 100644 src/CattyTests/Formula/FormulaParserOperatorsTest.swift create mode 100644 src/CattyTests/Formula/FormulaTestHelper.swift diff --git a/src/Catty.xcodeproj/project.pbxproj b/src/Catty.xcodeproj/project.pbxproj index 2dddb92160..3db83f5485 100644 --- a/src/Catty.xcodeproj/project.pbxproj +++ b/src/Catty.xcodeproj/project.pbxproj @@ -633,17 +633,14 @@ 4C4778E6267C83C000CAF398 /* URLSession.jsonDataTask.success.json in Resources */ = {isa = PBXBuildFile; fileRef = 4C4778E5267C83C000CAF398 /* URLSession.jsonDataTask.success.json */; }; 4C4778F5267C83F500CAF398 /* InternFormulaStateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C4778E8267C83F500CAF398 /* InternFormulaStateTest.m */; }; 4C4778F6267C83F500CAF398 /* FormulaTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C4778E9267C83F500CAF398 /* FormulaTest.swift */; }; - 4C4778F7267C83F500CAF398 /* FormulaParserFunctionsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C4778EA267C83F500CAF398 /* FormulaParserFunctionsTest.m */; }; 4C4778F8267C83F500CAF398 /* FormulaParserTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C4778EB267C83F500CAF398 /* FormulaParserTest.swift */; }; 4C4778F9267C83F500CAF398 /* InternFormulaUtilsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C4778EC267C83F500CAF398 /* InternFormulaUtilsTest.m */; }; 4C4778FA267C83F500CAF398 /* InternFormulaTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C4778ED267C83F500CAF398 /* InternFormulaTest.m */; }; 4C4778FB267C83F500CAF398 /* InternFormulaParserStringFunctionsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C4778EE267C83F500CAF398 /* InternFormulaParserStringFunctionsTest.m */; }; - 4C4778FC267C83F500CAF398 /* FormulaParserOperatorsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C4778EF267C83F500CAF398 /* FormulaParserOperatorsTest.m */; }; 4C4778FD267C83F500CAF398 /* FormulaElementTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C4778F0267C83F500CAF398 /* FormulaElementTest.swift */; }; 4C4778FE267C83F500CAF398 /* InternFormulaKeyboardAdapterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C4778F1267C83F500CAF398 /* InternFormulaKeyboardAdapterTests.swift */; }; 4C4778FF267C83F500CAF398 /* FormulaFunctionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C4778F2267C83F500CAF398 /* FormulaFunctionsTest.swift */; }; 4C477900267C83F500CAF398 /* InternFormulaTokenSelectionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C4778F3267C83F500CAF398 /* InternFormulaTokenSelectionTest.m */; }; - 4C477901267C83F500CAF398 /* FormulaParserErrorDetectionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C4778F4267C83F500CAF398 /* FormulaParserErrorDetectionTest.m */; }; 4C477903267C847800CAF398 /* UserListFunctionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C477902267C847800CAF398 /* UserListFunctionsTest.swift */; }; 4C477906267C849100CAF398 /* FormulaEditorItemTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C477905267C849100CAF398 /* FormulaEditorItemTest.swift */; }; 4C47790A267C87DE00CAF398 /* URLSession.jsonDataTask.fail.json in Resources */ = {isa = PBXBuildFile; fileRef = 4C477909267C87DE00CAF398 /* URLSession.jsonDataTask.fail.json */; }; @@ -1721,6 +1718,10 @@ AAF6D9DE1BC0C1F300686849 /* PlaceAtBrick+Instruction.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAF6D9DD1BC0C1F300686849 /* PlaceAtBrick+Instruction.swift */; }; AAF6D9E01BC0C2AA00686849 /* PointInDirectionBrick+Instruction.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAF6D9DF1BC0C2AA00686849 /* PointInDirectionBrick+Instruction.swift */; }; AAF6D9E21BC0C48300686849 /* PointToBrick+Instruction.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAF6D9E11BC0C48300686849 /* PointToBrick+Instruction.swift */; }; + ACBEB7A529A276C000D9D711 /* FormulaParserErrorDetectionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACBEB7A129A276C000D9D711 /* FormulaParserErrorDetectionTest.swift */; }; + ACBEB7A629A276C000D9D711 /* FormulaParserFunctionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACBEB7A229A276C000D9D711 /* FormulaParserFunctionsTest.swift */; }; + ACBEB7A729A276C000D9D711 /* FormulaParserOperatorsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACBEB7A329A276C000D9D711 /* FormulaParserOperatorsTest.swift */; }; + ACBEB7A829A276C000D9D711 /* FormulaTestHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACBEB7A429A276C000D9D711 /* FormulaTestHelper.swift */; }; BA1FA9981F02AD770084184D /* InsertItemIntoUserListBrick+CBXMLHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = BA1FA9971F02AD770084184D /* InsertItemIntoUserListBrick+CBXMLHandler.m */; }; BA1FA99D1F02AEDC0084184D /* InsertItemIntoUserListBrick.m in Sources */ = {isa = PBXBuildFile; fileRef = BA1FA99C1F02AEDC0084184D /* InsertItemIntoUserListBrick.m */; }; BA1FA9A01F02B0020084184D /* InsertItemIntoUserListBrickCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BA1FA99F1F02B0020084184D /* InsertItemIntoUserListBrickCell.m */; }; @@ -2800,17 +2801,14 @@ 4C4778E5267C83C000CAF398 /* URLSession.jsonDataTask.success.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = URLSession.jsonDataTask.success.json; sourceTree = ""; }; 4C4778E8267C83F500CAF398 /* InternFormulaStateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InternFormulaStateTest.m; sourceTree = ""; }; 4C4778E9267C83F500CAF398 /* FormulaTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormulaTest.swift; sourceTree = ""; }; - 4C4778EA267C83F500CAF398 /* FormulaParserFunctionsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FormulaParserFunctionsTest.m; sourceTree = ""; }; 4C4778EB267C83F500CAF398 /* FormulaParserTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormulaParserTest.swift; sourceTree = ""; }; 4C4778EC267C83F500CAF398 /* InternFormulaUtilsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InternFormulaUtilsTest.m; sourceTree = ""; }; 4C4778ED267C83F500CAF398 /* InternFormulaTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InternFormulaTest.m; sourceTree = ""; }; 4C4778EE267C83F500CAF398 /* InternFormulaParserStringFunctionsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InternFormulaParserStringFunctionsTest.m; sourceTree = ""; }; - 4C4778EF267C83F500CAF398 /* FormulaParserOperatorsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FormulaParserOperatorsTest.m; sourceTree = ""; }; 4C4778F0267C83F500CAF398 /* FormulaElementTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormulaElementTest.swift; sourceTree = ""; }; 4C4778F1267C83F500CAF398 /* InternFormulaKeyboardAdapterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InternFormulaKeyboardAdapterTests.swift; sourceTree = ""; }; 4C4778F2267C83F500CAF398 /* FormulaFunctionsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormulaFunctionsTest.swift; sourceTree = ""; }; 4C4778F3267C83F500CAF398 /* InternFormulaTokenSelectionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InternFormulaTokenSelectionTest.m; sourceTree = ""; }; - 4C4778F4267C83F500CAF398 /* FormulaParserErrorDetectionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FormulaParserErrorDetectionTest.m; sourceTree = ""; }; 4C477902267C847800CAF398 /* UserListFunctionsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserListFunctionsTest.swift; sourceTree = ""; }; 4C477905267C849100CAF398 /* FormulaEditorItemTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormulaEditorItemTest.swift; sourceTree = ""; }; 4C477909267C87DE00CAF398 /* URLSession.jsonDataTask.fail.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = URLSession.jsonDataTask.fail.json; sourceTree = ""; }; @@ -4336,6 +4334,10 @@ AAF6D9DF1BC0C2AA00686849 /* PointInDirectionBrick+Instruction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "PointInDirectionBrick+Instruction.swift"; path = "PlayerEngine/Instructions/Motion/PointInDirectionBrick+Instruction.swift"; sourceTree = ""; }; AAF6D9E11BC0C48300686849 /* PointToBrick+Instruction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "PointToBrick+Instruction.swift"; path = "PlayerEngine/Instructions/Motion/PointToBrick+Instruction.swift"; sourceTree = ""; }; ABD74577198FBC2984BDDE56 /* hu */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/Localizable.strings; sourceTree = ""; }; + ACBEB7A129A276C000D9D711 /* FormulaParserErrorDetectionTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormulaParserErrorDetectionTest.swift; sourceTree = ""; }; + ACBEB7A229A276C000D9D711 /* FormulaParserFunctionsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormulaParserFunctionsTest.swift; sourceTree = ""; }; + ACBEB7A329A276C000D9D711 /* FormulaParserOperatorsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormulaParserOperatorsTest.swift; sourceTree = ""; }; + ACBEB7A429A276C000D9D711 /* FormulaTestHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormulaTestHelper.swift; sourceTree = ""; }; B11EA657D0D5E2E348790671 /* ta */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.strings; name = ta; path = ta.lproj/Localizable.strings; sourceTree = ""; }; B46B270517703F9400172837 /* CattyTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "CattyTests-Info.plist"; sourceTree = ""; }; B46B270717703F9400172837 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -6278,10 +6280,11 @@ children = ( 4C477904267C849100CAF398 /* Dto */, 4C4778F0267C83F500CAF398 /* FormulaElementTest.swift */, + ACBEB7A129A276C000D9D711 /* FormulaParserErrorDetectionTest.swift */, + ACBEB7A229A276C000D9D711 /* FormulaParserFunctionsTest.swift */, + ACBEB7A329A276C000D9D711 /* FormulaParserOperatorsTest.swift */, + ACBEB7A429A276C000D9D711 /* FormulaTestHelper.swift */, 4C4778F2267C83F500CAF398 /* FormulaFunctionsTest.swift */, - 4C4778F4267C83F500CAF398 /* FormulaParserErrorDetectionTest.m */, - 4C4778EA267C83F500CAF398 /* FormulaParserFunctionsTest.m */, - 4C4778EF267C83F500CAF398 /* FormulaParserOperatorsTest.m */, 4C4778EB267C83F500CAF398 /* FormulaParserTest.swift */, 4C4778E9267C83F500CAF398 /* FormulaTest.swift */, 4C4778F1267C83F500CAF398 /* InternFormulaKeyboardAdapterTests.swift */, @@ -12273,6 +12276,7 @@ 056677F127DD39D8006B4477 /* ZigzagStitchPatternTests.swift in Sources */, 4C4778D6267C82B100CAF398 /* UIViewControllerExtensionTests.swift in Sources */, 498C156B2807057B00B81C8E /* ShoulderSensorTest.swift in Sources */, + ACBEB7A729A276C000D9D711 /* FormulaParserOperatorsTest.swift in Sources */, 17A8AC652644E6A900DDD480 /* ForceInit.m in Sources */, 4C2732A91CE4F30F00CA61AC /* CBSpriteNodeTests.swift in Sources */, 4C6FE169212D2D2E0067B7D5 /* ExpFunctionTest.swift in Sources */, @@ -12338,7 +12342,6 @@ E5E6D84626A83FDD0073C010 /* CBXMLParserContextTests.swift in Sources */, 4C0F9FD5204BD3C200E71B2D /* ChooseCameraBrickTests.swift in Sources */, CA7698C21B0E4B3F000D0340 /* CBStackTests.m in Sources */, - 4C4778FC267C83F500CAF398 /* FormulaParserOperatorsTest.m in Sources */, 4C822679213FA7A400F3D750 /* SizeSensorTest.swift in Sources */, 2E7ED10625E38E1A0009F17F /* WebRequestDownloaderTests.swift in Sources */, 46C5D9F6254FF641003D58D9 /* RotationStyleTests.swift in Sources */, @@ -12357,6 +12360,7 @@ 59BA5C6825E3EC9500CBD5CF /* StoreProjectDownloaderErrorTests.swift in Sources */, 4C4778DC267C82B100CAF398 /* UIColorExtensionTests.swift in Sources */, 4C6FE16E212D2D2E0067B7D5 /* AsinFunctionTest.swift in Sources */, + ACBEB7A629A276C000D9D711 /* FormulaParserFunctionsTest.swift in Sources */, 4C2CBB4425A5AA8400C1C143 /* SceneXMLHandlerTest.m in Sources */, 4CB04BE12541618A00D85C31 /* StagePresenterViewControllerScreenshotTests.swift in Sources */, 926197F01BF3249E006D1A61 /* ArduinoTests.swift in Sources */, @@ -12473,7 +12477,6 @@ 49402BA1281178C1009FCBF8 /* PinkySensorTest.swift in Sources */, 4C82266B213FA7A400F3D750 /* DateYearSensorTest.swift in Sources */, 4C3A5C9921D3B23E008FD83F /* PlusOperatorTest.swift in Sources */, - 4C4778F7267C83F500CAF398 /* FormulaParserFunctionsTest.m in Sources */, 4C2CBB5125A5AA8400C1C143 /* XMLParserTests092.swift in Sources */, 4C2CBB4D25A5AA8400C1C143 /* XMLParserFormulaTests095.swift in Sources */, 4CEB22761B95E4BC00B3BE2F /* BrickInsertManagerRepeatTests.m in Sources */, @@ -12641,6 +12644,7 @@ 0594CE64275E55CD007DC3F9 /* SewUpTests.swift in Sources */, 498C156D2807057B00B81C8E /* NeckSensorTest.swift in Sources */, 9E3AF7982326F21300AB16F1 /* SetXBrickTests.swift in Sources */, + ACBEB7A529A276C000D9D711 /* FormulaParserErrorDetectionTest.swift in Sources */, 4C4B4CDF23EE98C80054C861 /* CustomAlertControllerTests.swift in Sources */, 4C822678213FA7A400F3D750 /* ColorSensorTest.swift in Sources */, 4974B2BB281A5F6300EEF0D9 /* TextBlockTextFunctionTest.swift in Sources */, @@ -12649,6 +12653,7 @@ 4C0C164921439B2F005ADE86 /* ChartProjectsStoreDataSourceTests.swift in Sources */, 4CC50A62213BE4D3004BC914 /* DoubleParameterDoubleFunctionMock.swift in Sources */, E579F111253DB124009107C8 /* SayForBubbleBrickTests.swift in Sources */, + ACBEB7A829A276C000D9D711 /* FormulaTestHelper.swift in Sources */, 4CB23D7221E6613D00A0FEA7 /* DeleteItemOfUserListBrickTests.swift in Sources */, 4C4778E2267C82B100CAF398 /* UIImageExtensionTests.swift in Sources */, D3CF3A0F23D07F06006B2667 /* ProjectMock.swift in Sources */, @@ -12671,7 +12676,6 @@ 9E22655F22BFB3FC00898052 /* AudioPlayerTests.swift in Sources */, 4C82267E213FA7A400F3D750 /* LayerSensorTest.swift in Sources */, 9E544D35238754C500935C17 /* SpeechSynthesizerIntegrationTests.swift in Sources */, - 4C477901267C83F500CAF398 /* FormulaParserErrorDetectionTest.m in Sources */, 18B9A1BA24A75F3C009028F8 /* SetPenSizeBrickTests.swift in Sources */, 4C1AA4AE21A1572700DAC589 /* MediaItemTest.swift in Sources */, D30ECD1D2440963100FAD17D /* CBFilterDisabledTests.swift in Sources */, diff --git a/src/CattyTests/Formula/FormulaParserErrorDetectionTest.m b/src/CattyTests/Formula/FormulaParserErrorDetectionTest.m deleted file mode 100644 index 00585daa5b..0000000000 --- a/src/CattyTests/Formula/FormulaParserErrorDetectionTest.m +++ /dev/null @@ -1,166 +0,0 @@ -/** - * Copyright (C) 2010-2023 The Catrobat Team - * (http://developer.catrobat.org/credits) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * An additional term exception under section 7 of the GNU Affero - * General Public License, version 3, is available at - * (http://developer.catrobat.org/license_additional_term) - * - * This program 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. - */ - -#import -#import "Formula.h" -#import "FormulaElement.h" -#import "InternToken.h" -#import "InternFormulaParser.h" -#import "InternFormulaParserException.h" -#import "SpriteObject.h" -#import -#include -#import "Pocket_Code-Swift.h" - -@interface FormulaParserErrorDetectionTest : XCTestCase -@property(nonatomic, strong) FormulaManager* formulaManager; -@end - -@implementation FormulaParserErrorDetectionTest - -- (void)setUp { - [super setUp]; - self.formulaManager = [[FormulaManager alloc] initWithStageSize:[Util screenSize:true] andLandscapeMode: false]; -} - -- (void)testTooManyOperators -{ - NSMutableArray *internTokenList = [[NSMutableArray alloc] init]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_OPERATOR AndValue:MinusOperator.tag]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_OPERATOR AndValue:MinusOperator.tag]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:@"42.42"]]; - - InternFormulaParser *internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - FormulaElement *parseTree = [internParser parseFormulaForSpriteObject:nil]; - - XCTAssertNil(parseTree, @"Invalid formula parsed: - - 42.42"); - XCTAssertEqual(1, internParser.errorTokenIndex, @"Error Token Index is not as expected"); - - [internTokenList removeAllObjects]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_OPERATOR AndValue:PlusOperator.tag]]; - - internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - parseTree = [internParser parseFormulaForSpriteObject:nil]; - - XCTAssertNil(parseTree, @"Invalid formula parsed: +"); - XCTAssertEqual(0, internParser.errorTokenIndex, @"Error Token Index is not as expected"); - - [internTokenList removeAllObjects]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_OPERATOR AndValue:MinusOperator.tag]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_OPERATOR AndValue:PlusOperator.tag]]; - - internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - parseTree = [internParser parseFormulaForSpriteObject:nil]; - - XCTAssertNil(parseTree, @"Invalid formula parsed: + -"); - XCTAssertEqual(1, internParser.errorTokenIndex, @"Error Token Index is not as expected"); - - [internTokenList removeAllObjects]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_OPERATOR AndValue:MultOperator.tag]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:@"42.53"]]; - - internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - parseTree = [internParser parseFormulaForSpriteObject:nil]; - - XCTAssertNil(parseTree, @"Invalid formula parsed: * 42.53"); - XCTAssertEqual(0, internParser.errorTokenIndex, @"Error Token Index is not as expected"); - - [internTokenList removeAllObjects]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_OPERATOR AndValue:MinusOperator.tag]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:@"42.42"]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_OPERATOR AndValue:MinusOperator.tag]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:@"42.42"]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_OPERATOR AndValue:MinusOperator.tag]]; - - internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - parseTree = [internParser parseFormulaForSpriteObject:nil]; - - XCTAssertNil(parseTree, @"Invalid formula parsed: - 42.42 - 42.42 -"); - XCTAssertEqual(5, internParser.errorTokenIndex, @"Error Token Index is not as expected"); -} - -- (void) testOperatorMissing -{ - NSMutableArray *internTokenList = [[NSMutableArray alloc] init]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:@"42.53"]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:@"42.52"]]; - - InternFormulaParser *internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - FormulaElement *parseTree = [internParser parseFormulaForSpriteObject:nil]; - - XCTAssertNil(parseTree, @"Invalid formula parsed: 42.53 42.42"); - XCTAssertEqual(1, internParser.errorTokenIndex, @"Error Token Index is not as expected"); -} - -- (void) testNumberMissing -{ - NSMutableArray *internTokenList = [[NSMutableArray alloc] init]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_OPERATOR AndValue:MultOperator.tag]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:@"42.53"]]; - - InternFormulaParser *internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - FormulaElement *parseTree = [internParser parseFormulaForSpriteObject:nil]; - - XCTAssertNil(parseTree, @"Invalid formula parsed: * 42.53"); - XCTAssertEqual(0, internParser.errorTokenIndex, @"Error Token Index is not as expected"); -} - -- (void) testRightBracketMissing -{ - NSMutableArray *internTokenList = [[NSMutableArray alloc] init]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_BRACKET_OPEN]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:@"42.53"]]; - - InternFormulaParser *internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - FormulaElement *parseTree = [internParser parseFormulaForSpriteObject:nil]; - - XCTAssertNil(parseTree, @"Invalid formula parsed: (42.53"); - XCTAssertEqual(2, internParser.errorTokenIndex, @"Error Token Index is not as expected"); -} - -- (void) testLeftBracketMissing -{ - NSMutableArray *internTokenList = [[NSMutableArray alloc] init]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:@"42.53"]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_BRACKET_CLOSE]]; - - InternFormulaParser *internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - FormulaElement *parseTree = [internParser parseFormulaForSpriteObject:nil]; - - XCTAssertNil(parseTree, @"Invalid formula parsed: 42.53)"); - XCTAssertEqual(1, internParser.errorTokenIndex, @"Error Token Index is not as expected"); -} - -- (void) testOutOfBound -{ - NSMutableArray *internTokenList = [[NSMutableArray alloc] init]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:@"42.53"]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_BRACKET_CLOSE]]; - - InternFormulaParser *internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - FormulaElement *parseTree = [internParser parseFormulaForSpriteObject:nil]; - - XCTAssertNil(parseTree, "Invalid formula parsed: 42.53)"); - XCTAssertEqual(1, internParser.errorTokenIndex, @"Error Token Index is not as expected"); -} - -@end diff --git a/src/CattyTests/Formula/FormulaParserErrorDetectionTest.swift b/src/CattyTests/Formula/FormulaParserErrorDetectionTest.swift new file mode 100644 index 0000000000..2fec337220 --- /dev/null +++ b/src/CattyTests/Formula/FormulaParserErrorDetectionTest.swift @@ -0,0 +1,90 @@ +/** + * Copyright (C) 2010-2023 The Catrobat Team + * (http://developer.catrobat.org/credits) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * An additional term exception under section 7 of the GNU Affero + * General Public License, version 3, is available at + * (http://developer.catrobat.org/license_additional_term) + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ + +import XCTest + +@testable import Pocket_Code + +class FormulaParserErrorDetectionTest: XCTestCase { + + var formulaTestHelper: FormulaTestHelper! + + override func setUp() { + super.setUp() + formulaTestHelper = FormulaTestHelper() + } + + func testTooManyOperators() { + var internTokenList = [InternToken(type: TOKEN_TYPE_OPERATOR, andValue: MinusOperator.tag)!, + InternToken(type: TOKEN_TYPE_OPERATOR, andValue: MinusOperator.tag)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "42.42")!] + formulaTestHelper.interpretInvalidFormula(with: internTokenList, description: "Invalid formula parsed: - - 42.42", andExpectedErrorCode: 1) + + internTokenList = [InternToken(type: TOKEN_TYPE_OPERATOR, andValue: PlusOperator.tag)] + formulaTestHelper.interpretInvalidFormula(with: internTokenList, description: "Invalid formula parsed: +", andExpectedErrorCode: 0) + + internTokenList = [InternToken(type: TOKEN_TYPE_OPERATOR, andValue: MinusOperator.tag)!, + InternToken(type: TOKEN_TYPE_OPERATOR, andValue: PlusOperator.tag)!] + formulaTestHelper.interpretInvalidFormula(with: internTokenList, description: "Invalid formula parsed: + -", andExpectedErrorCode: 1) + + internTokenList = [InternToken(type: TOKEN_TYPE_OPERATOR, andValue: MultOperator.tag)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "42.53")!] + formulaTestHelper.interpretInvalidFormula(with: internTokenList, description: "Invalid formula parsed: * 42.53", andExpectedErrorCode: 0) + + internTokenList = [InternToken(type: TOKEN_TYPE_OPERATOR, andValue: MinusOperator.tag)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "42.42")!, + InternToken(type: TOKEN_TYPE_OPERATOR, andValue: MinusOperator.tag)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "42.42")!, + InternToken(type: TOKEN_TYPE_OPERATOR, andValue: MinusOperator.tag)!] + formulaTestHelper.interpretInvalidFormula(with: internTokenList, description: "Invalid formula parsed: - 42.42 - 42.42 -", andExpectedErrorCode: 5) + } + + func testOperatorMissing() { + let internTokenList = [InternToken(type: TOKEN_TYPE_NUMBER, andValue: "42.53")!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "42.42")!] + formulaTestHelper.interpretInvalidFormula(with: internTokenList, description: "Invalid formula parsed: 42.53 42.42", andExpectedErrorCode: 1) + } + + func testNumberMissing() { + let internTokenList = [InternToken(type: TOKEN_TYPE_OPERATOR, andValue: MultOperator.tag)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "42.53")!] + formulaTestHelper.interpretInvalidFormula(with: internTokenList, description: "Invalid formula parsed: * 42.53", andExpectedErrorCode: 0) + } + + func testRightBracketMissing() { + let internTokenList = [InternToken(type: TOKEN_TYPE_BRACKET_OPEN)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "42.53")!] + formulaTestHelper.interpretInvalidFormula(with: internTokenList, description: "Invalid formula parsed: (42.53", andExpectedErrorCode: 2) + } + + func testLeftBracketMissing() { + let internTokenList = [InternToken(type: TOKEN_TYPE_NUMBER, andValue: "42.53")!, + InternToken(type: TOKEN_TYPE_BRACKET_CLOSE)!] + formulaTestHelper.interpretInvalidFormula(with: internTokenList, description: "Invalid formula parsed: 42.53)", andExpectedErrorCode: 1) + } + + func testOutOfBound() { + let internTokenList = [InternToken(type: TOKEN_TYPE_NUMBER, andValue: "42.53")!, + InternToken(type: TOKEN_TYPE_BRACKET_CLOSE)!] + formulaTestHelper.interpretInvalidFormula(with: internTokenList, description: "Invalid formula parsed: 42.53)", andExpectedErrorCode: 1) + } +} diff --git a/src/CattyTests/Formula/FormulaParserFunctionsTest.m b/src/CattyTests/Formula/FormulaParserFunctionsTest.m deleted file mode 100644 index a9a49454a1..0000000000 --- a/src/CattyTests/Formula/FormulaParserFunctionsTest.m +++ /dev/null @@ -1,362 +0,0 @@ -/** - * Copyright (C) 2010-2023 The Catrobat Team - * (http://developer.catrobat.org/credits) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * An additional term exception under section 7 of the GNU Affero - * General Public License, version 3, is available at - * (http://developer.catrobat.org/license_additional_term) - * - * This program 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. - */ - -#import -#import "Formula.h" -#import "FormulaElement.h" -#import "InternToken.h" -#import "InternFormulaParser.h" -#import "InternFormulaParserException.h" -#import "SpriteObject.h" -#import "Util.h" -#import -#include -#import "Pocket_Code-Swift.h" - -@interface FormulaParserFunctionsTest : XCTestCase -@property (nonatomic, strong) FormulaManager* formulaManager; -@property (nonatomic, strong) id interpreter; -@property (nonatomic, strong) SpriteObject *spriteObject; -@end - -@implementation FormulaParserFunctionsTest - -#define EPSILON 0.01 - -- (void)setUp -{ - self.formulaManager = [[FormulaManager alloc] initWithStageSize:[Util screenSize:true] andLandscapeMode: false]; - self.interpreter = (id)self.formulaManager; - self.spriteObject = [[SpriteObject alloc] init]; -} - -- (void) testSin -{ - Formula *formula = [self getFormula:@"SIN" value:@"90"]; // TODO use Function property - XCTAssertNotNil(formula, @"Formula is not parsed correctly: sin(90)"); - XCTAssertEqual(1, [self.interpreter interpretDouble:formula forSpriteObject:self.spriteObject], @"Formula interpretation is not as expected"); -} - -- (void) testCos -{ - Formula *formula = [self getFormula:@"COS" value:@"180"]; // TODO use Function property - XCTAssertNotNil(formula, @"Formula is not parsed correctly: cos(180)"); - XCTAssertEqual(-1, [self.interpreter interpretDouble:formula forSpriteObject:self.spriteObject], @"Formula interpretation is not as expected"); -} - -- (void) testTan -{ - Formula *formula = [self getFormula:@"TAN" value:@"180"]; // TODO use Function property - XCTAssertNotNil(formula, @"Formula is not parsed correctly: tan(180)"); - XCTAssertEqualWithAccuracy(0, [self.interpreter interpretDouble:formula forSpriteObject:self.spriteObject], EPSILON, @"Formula interpretation is not as expected"); -} - -- (void) testLn -{ - Formula *formula = [self getFormula:@"LN" value:@"2.7182818"]; // TODO use Function property - XCTAssertNotNil(formula, @"Formula is not parsed correctly: ln(e)"); - XCTAssertEqualWithAccuracy(1, [self.interpreter interpretDouble:formula forSpriteObject:self.spriteObject], EPSILON, @"Formula interpretation is not as expected"); -} - -- (void) testLog -{ - Formula *formula = [self getFormula:@"LOG" value:@"10"]; // TODO use Function property - XCTAssertNotNil(formula, @"Formula is not parsed correctly: log(10)"); - XCTAssertEqual(1, [self.interpreter interpretDouble:formula forSpriteObject:self.spriteObject], @"Formula interpretation is not as expected"); -} - -- (void) testPi -{ - NSMutableArray *internTokenList = [[NSMutableArray alloc] init]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_NAME AndValue:@"PI"]]; // TODO use Function property - - InternFormulaParser *internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - FormulaElement *parseTree = [internParser parseFormulaForSpriteObject:nil]; - - XCTAssertNotNil(parseTree, @"Formula is not parsed correctly: pi"); - - Formula *formula = [[Formula alloc] initWithFormulaElement:parseTree]; - XCTAssertEqual(M_PI, [self.interpreter interpretDouble:formula forSpriteObject:self.spriteObject], @"Formula interpretation is not as expected"); -} - -- (void) testSqrt -{ - Formula *formula = [self getFormula:@"SQRT" value:@"100"]; // TODO use Function property - XCTAssertNotNil(formula, @"Formula is not parsed correctly: sqrt(100)"); - XCTAssertEqual(10, [self.interpreter interpretDouble:formula forSpriteObject:self.spriteObject], @"Formula interpretation is not as expected"); -} - -- (void) testExp -{ - Formula *formula = [self getFormula:@"EXP" value:@"3"]; // TODO use Function property - XCTAssertNotNil(formula, @"Formula is not parsed correctly: exp(0)"); - XCTAssertEqualWithAccuracy(20.08f, [self.interpreter interpretDouble:formula forSpriteObject:self.spriteObject], 0.1f, @"Formula interpretation is not as expected"); -} - -- (void) testRandomNaturalNumbers -{ - NSMutableArray *internTokenList = [[NSMutableArray alloc] init]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_NAME AndValue:@"RAND"]]; // TODO use Function property - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_OPEN]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:@"0"]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETER_DELIMITER]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:@"1"]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE]]; - - InternFormulaParser *internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - FormulaElement *parseTree = [internParser parseFormulaForSpriteObject:nil]; - - XCTAssertNotNil(parseTree, @"Formula is not parsed correctly: random(0,1)"); - - Formula *formula = [[Formula alloc] initWithFormulaElement:parseTree]; - double result = [self.interpreter interpretDouble:formula forSpriteObject:self.spriteObject]; - XCTAssertTrue(result == 0 || result == 1, @"Formula interpretation is not as expected"); -} - -- (void) testRound -{ - Formula *formula = [self getFormula:@"ROUND" value:@"1.33333"]; // TODO use Function property - XCTAssertNotNil(formula, @"Formula is not parsed correctly: round(1.33333)"); - XCTAssertEqual(1, [self.interpreter interpretDouble:formula forSpriteObject:self.spriteObject], @"Formula interpretation is not as expected"); -} - -- (void) testMod -{ - for (int offset = 0; offset < 10; offset += 1) { - int dividend = 1 + offset; - int divisor = 1 + offset; - - NSMutableArray *internTokenList = [[NSMutableArray alloc] init]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_NAME AndValue:@"MOD"]]; // TODO use Function property - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_OPEN]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:[NSString stringWithFormat:@"%i", dividend]]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETER_DELIMITER]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:[NSString stringWithFormat:@"%i", divisor]]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE]]; - - InternFormulaParser *internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - FormulaElement *parseTree = [internParser parseFormulaForSpriteObject:nil]; - - XCTAssertNotNil(parseTree, "Formula is not parsed correctly: mod(%i, %i)", dividend, divisor); - - Formula *formula = [[Formula alloc] initWithFormulaElement:parseTree]; - XCTAssertEqualWithAccuracy(0, [self.interpreter interpretDouble:formula forSpriteObject:self.spriteObject], EPSILON, @"Formula interpretation is not as expected"); - } - - for (int offset = 0; offset < 100; offset += 2) { - int dividend = 3 + offset; - int divisor = 2 + offset; - - NSMutableArray *internTokenList = [[NSMutableArray alloc] init]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_NAME AndValue:@"MOD"]]; // TODO use Function property - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_OPEN]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:[NSString stringWithFormat:@"%i", dividend]]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETER_DELIMITER]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:[NSString stringWithFormat:@"%i", divisor]]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE]]; - - InternFormulaParser *internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - FormulaElement *parseTree = [internParser parseFormulaForSpriteObject:nil]; - - XCTAssertNotNil(parseTree, "Formula is not parsed correctly: mod(%i, %i)", dividend, divisor); - - Formula *formula = [[Formula alloc] initWithFormulaElement:parseTree]; - XCTAssertEqualWithAccuracy(1, [self.interpreter interpretDouble:formula forSpriteObject:self.spriteObject], EPSILON, @"Formula interpretation is not as expected"); - } - - for (int offset = 0; offset < 10; offset += 1) { - int dividend = 3 + offset; - int divisor = 5 + offset; - - NSMutableArray *internTokenList = [[NSMutableArray alloc] init]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_NAME AndValue:@"MOD"]]; // TODO use Function property - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_OPEN]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:[NSString stringWithFormat:@"%i", dividend]]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETER_DELIMITER]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:[NSString stringWithFormat:@"%i", divisor]]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE]]; - - InternFormulaParser *internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - FormulaElement *parseTree = [internParser parseFormulaForSpriteObject:nil]; - - XCTAssertNotNil(parseTree, "Formula is not parsed correctly: mod(%i, %i)", dividend, divisor); - - Formula *formula = [[Formula alloc] initWithFormulaElement:parseTree]; - XCTAssertEqualWithAccuracy(dividend, [self.interpreter interpretDouble:formula forSpriteObject:self.spriteObject], EPSILON, "Formula interpretation is not as expected"); - } - - for (int offset = 0; offset < 10; offset += 1) { - int dividend = -3 - offset; - int divisor = 2 + offset; - - NSMutableArray *internTokenList = [[NSMutableArray alloc] init]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_NAME AndValue:@"MOD"]]; // TODO use Function property - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_OPEN]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_OPERATOR AndValue:MinusOperator.tag]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:[NSString stringWithFormat:@"%i", abs(dividend)]]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETER_DELIMITER]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:[NSString stringWithFormat:@"%i", divisor]]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE]]; - - InternFormulaParser *internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - FormulaElement *parseTree = [internParser parseFormulaForSpriteObject:nil]; - - XCTAssertNotNil(parseTree, @"Formula is not parsed correctly: mod(%i, %i)", dividend, divisor); - - Formula *formula = [[Formula alloc] initWithFormulaElement:parseTree]; - XCTAssertEqualWithAccuracy(1 + offset, [self.interpreter interpretDouble:formula forSpriteObject:self.spriteObject], EPSILON, @"Formula interpretation is not as expected"); - } -} - -- (void) testAbs -{ - NSMutableArray *internTokenList = [[NSMutableArray alloc] init]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_NAME AndValue:@"ABS"]]; // TODO use Function property - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_OPEN]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_OPERATOR AndValue:MinusOperator.tag]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:@"1"]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE]]; - - InternFormulaParser *internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - FormulaElement *parseTree = [internParser parseFormulaForSpriteObject:nil]; - - XCTAssertNotNil(parseTree, @"Formula is not parsed correctly: abs(-1)"); - - Formula *formula = [[Formula alloc] initWithFormulaElement:parseTree]; - XCTAssertEqual(1, [self.interpreter interpretDouble:formula forSpriteObject:self.spriteObject], @"Formula interpretation is not as expected"); -} - -- (void) testInvalidFunction -{ - NSMutableArray *internTokenList = [[NSMutableArray alloc] init]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_NAME AndValue:@"INVALID_FUNCTION"]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_OPEN]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:@"1"]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE]]; - - InternFormulaParser *internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - FormulaElement *parseTree = [internParser parseFormulaForSpriteObject:nil]; - - XCTAssertNil(parseTree, @"Formula parsed but should not: INVALID_FUNCTION(1)"); - XCTAssertEqual(0, internParser.errorTokenIndex, @"Formula error value is not as expected"); -} - -- (void) testTrue -{ - NSMutableArray *internTokenList = [[NSMutableArray alloc] init]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_NAME AndValue:@"TRUE"]]; // TODO use Function property - - InternFormulaParser *internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - FormulaElement *parseTree = [internParser parseFormulaForSpriteObject:nil]; - - XCTAssertNotNil(parseTree, @"Formula is not parsed correctly: true"); - - Formula *formula = [[Formula alloc] initWithFormulaElement:parseTree]; - XCTAssertEqual(1.0, [self.interpreter interpretDouble:formula forSpriteObject:self.spriteObject], @"Formula interpretation is not as expected"); -} - -- (void) testFalse -{ - NSMutableArray *internTokenList = [[NSMutableArray alloc] init]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_NAME AndValue:@"FALSE"]]; // TODO use Function property - - InternFormulaParser *internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - FormulaElement *parseTree = [internParser parseFormulaForSpriteObject:nil]; - - XCTAssertNotNil(parseTree, @"Formula is not parsed correctly: false"); - - Formula *formula = [[Formula alloc] initWithFormulaElement:parseTree]; - XCTAssertEqual(0.0, [self.interpreter interpretDouble:formula forSpriteObject:self.spriteObject], @"Formula interpretation is not as expected"); -} - -- (void) testArcsin -{ - Formula *formula = [self getFormula:@"ARCSIN" value:@"1"]; // TODO use Function property - XCTAssertNotNil(formula, @"Formula is not parsed correctly: arcsin(1)"); - XCTAssertEqualWithAccuracy(90, [self.interpreter interpretDouble:formula forSpriteObject:self.spriteObject], EPSILON, @"Formula interpretation is not as expected"); -} - -- (void) testArccos -{ - Formula *formula = [self getFormula:@"ARCCOS" value:@"0"]; // TODO use Function property - XCTAssertNotNil(formula, @"Formula is not parsed correctly: arccos(0)"); - XCTAssertEqualWithAccuracy(90, [self.interpreter interpretDouble:formula forSpriteObject:self.spriteObject], EPSILON, @"Formula interpretation is not as expected"); -} - -- (void) testArctan -{ - Formula *formula = [self getFormula:@"ARCTAN" value:@"1"]; // TODO use Function property - XCTAssertNotNil(formula, @"Formula is not parsed correctly: arctan(1)"); - XCTAssertEqualWithAccuracy(45, [self.interpreter interpretDouble:formula forSpriteObject:self.spriteObject], EPSILON, @"Formula interpretation is not as expected"); -} - -- (void) testMax -{ - NSMutableArray *internTokenList = [[NSMutableArray alloc] init]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_NAME AndValue:@"MAX"]]; // TODO use Function property - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_OPEN]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:@"3"]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETER_DELIMITER]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:@"4"]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE]]; - - InternFormulaParser *internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - FormulaElement *parseTree = [internParser parseFormulaForSpriteObject:nil]; - - XCTAssertNotNil(parseTree, @"Formula is not parsed correctly: max(3,4)"); - - Formula *formula = [[Formula alloc] initWithFormulaElement:parseTree]; - XCTAssertEqual(4, [self.interpreter interpretDouble:formula forSpriteObject:self.spriteObject], @"Formula interpretation is not as expected"); -} - -- (void) testMin -{ - NSMutableArray *internTokenList = [[NSMutableArray alloc] init]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_NAME AndValue:@"MIN"]]; // TODO use Function property - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_OPEN]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:@"3"]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETER_DELIMITER]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:@"4"]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE]]; - - InternFormulaParser *internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - FormulaElement *parseTree = [internParser parseFormulaForSpriteObject:nil]; - - XCTAssertNotNil(parseTree, @"Formula is not parsed correctly: min(3,4)"); - - Formula *formula = [[Formula alloc] initWithFormulaElement:parseTree]; - XCTAssertEqual(3, [self.interpreter interpretDouble:formula forSpriteObject:self.spriteObject], @"Formula interpretation is not as expected"); -} - -- (Formula*)getFormula:(NSString*)tag value:(NSString*)value -{ - NSMutableArray *internTokenList = [[NSMutableArray alloc] init]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_NAME AndValue:tag]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_OPEN]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:value]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE]]; - - InternFormulaParser *internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - return [[Formula alloc] initWithFormulaElement:[internParser parseFormulaForSpriteObject:nil]]; -} - -@end diff --git a/src/CattyTests/Formula/FormulaParserFunctionsTest.swift b/src/CattyTests/Formula/FormulaParserFunctionsTest.swift new file mode 100644 index 0000000000..1dff781271 --- /dev/null +++ b/src/CattyTests/Formula/FormulaParserFunctionsTest.swift @@ -0,0 +1,219 @@ +/** + * Copyright (C) 2010-2023 The Catrobat Team + * (http://developer.catrobat.org/credits) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * An additional term exception under section 7 of the GNU Affero + * General Public License, version 3, is available at + * (http://developer.catrobat.org/license_additional_term) + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ + +import XCTest + +@testable import Pocket_Code + +class FormulaParserFunctionsTest: XCTestCase { + + var formulaTestHelper: FormulaTestHelper! + let EPSILON = 0.01 + + override func setUp() { + super.setUp() + formulaTestHelper = FormulaTestHelper() + } + + func testSin() { + let internTokenList = addOpeningAndClosingBrackets(withTag: "SIN", andValue: "90") + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "sin(90)", andExpectedResult: 1) + } + + func testCos() { + let internTokenList = addOpeningAndClosingBrackets(withTag: "COS", andValue: "180") + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "cos(90)", andExpectedResult: -1) + } + + func testTan() { + let internTokenList = addOpeningAndClosingBrackets(withTag: "TAN", andValue: "180") + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "tan(90)", andExpectedResult: 0.0, withAccuracy: EPSILON) + } + + func testLn() { + let internTokenList = addOpeningAndClosingBrackets(withTag: "LN", andValue: "2.7182818") + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "ln(2.7182818)", andExpectedResult: 1.0, withAccuracy: EPSILON) + } + + func testLog() { + let internTokenList = addOpeningAndClosingBrackets(withTag: "LOG", andValue: "10") + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "log(10)", andExpectedResult: 1) + } + + func testPi() { + let internTokenList = [InternToken(type: TOKEN_TYPE_FUNCTION_NAME, andValue: "PI")!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "PI", andExpectedResult: Double.pi) + } + + func testSqrt() { + let internTokenList = addOpeningAndClosingBrackets(withTag: "SQRT", andValue: "100") + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "sqrt(100)", andExpectedResult: 10) + } + + func testExp() { + let internTokenList = addOpeningAndClosingBrackets(withTag: "EXP", andValue: "3") + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "exp(3)", andExpectedResult: 20.08, withAccuracy: 0.1) + } + + func testRandomNaturalNumbers() { + let internTokenList = [InternToken(type: TOKEN_TYPE_FUNCTION_NAME, andValue: "RAND")!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_OPEN)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "0")!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETER_DELIMITER)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE)!] + let parser = InternFormulaParser(tokens: internTokenList, andFormulaManager: formulaTestHelper.formulaManager) + let parseTree = parser?.parseFormula(for: nil) + XCTAssertNotNil(parseTree, "Formula is not parsed correctly!") + + let formula = Formula(formulaElement: parseTree)! + let result = formulaTestHelper.interpreter.interpretDouble(formula, for: formulaTestHelper.spriteObject) + XCTAssertTrue(result == 1 || result == 0, "Formula interpretation is not as expected!") + } + + func testRound() { + let internTokenList = addOpeningAndClosingBrackets(withTag: "ROUND", andValue: "1.33333") + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "round(1.33333)", andExpectedResult: 1.0) + } + + func testMod() { + for offset in 0...9 { + let dividend = 1 + offset + let divisor = 1 + offset + let internTokenList = [InternToken(type: TOKEN_TYPE_FUNCTION_NAME, andValue: "MOD")!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_OPEN)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: String(dividend))!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETER_DELIMITER)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: String(divisor))!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE)!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "mod(\(dividend), \(divisor))", andExpectedResult: 0.0, withAccuracy: EPSILON) + } + + for offset in stride(from: 0, to: 100, by: 2) { + let dividend = 3 + offset + let divisor = 2 + offset + let internTokenList = [InternToken(type: TOKEN_TYPE_FUNCTION_NAME, andValue: "MOD")!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_OPEN)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: String(dividend))!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETER_DELIMITER)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: String(divisor))!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE)!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "mod(\(dividend), \(divisor))", andExpectedResult: 1.0, withAccuracy: EPSILON) + } + + for offset in 0...9 { + let dividend = 3 + offset + let divisor = 5 + offset + let internTokenList = [InternToken(type: TOKEN_TYPE_FUNCTION_NAME, andValue: "MOD")!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_OPEN)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: String(dividend))!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETER_DELIMITER)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: String(divisor))!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE)!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "mod(\(dividend), \(divisor))", andExpectedResult: Double(dividend), withAccuracy: EPSILON) + } + + for offset in 0...9 { + let dividend = -3 - offset + let divisor = 2 + offset + let internTokenList = [InternToken(type: TOKEN_TYPE_FUNCTION_NAME, andValue: "MOD")!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_OPEN)!, + InternToken(type: TOKEN_TYPE_OPERATOR, andValue: MinusOperator.tag)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: String(abs(dividend)))!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETER_DELIMITER)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: String(divisor))!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE)!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "mod(-\(abs(dividend)), \(divisor))", andExpectedResult: Double(1 + offset), withAccuracy: EPSILON) + } + } + + func testAbs() { + let internTokenList = [InternToken(type: TOKEN_TYPE_FUNCTION_NAME, andValue: "ABS")!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_OPEN)!, + InternToken(type: TOKEN_TYPE_OPERATOR, andValue: MinusOperator.tag)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE)!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "abs(1)", andExpectedResult: 1) + } + + func testInvalidFunction() { + let internTokenList = [InternToken(type: TOKEN_TYPE_FUNCTION_NAME, andValue: "INVALID_FUNCTION")!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_OPEN)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE)!] + formulaTestHelper.interpretInvalidFormula(with: internTokenList, description: "Formula parsed but should not: INVALID_FUNCTION(1)", andExpectedErrorCode: 0) + } + + func testTrue() { + let internTokenList = [InternToken(type: TOKEN_TYPE_FUNCTION_NAME, andValue: "TRUE")!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "TRUE", andExpectedResult: 1.0) + } + + func testFalse() { + let internTokenList = [InternToken(type: TOKEN_TYPE_FUNCTION_NAME, andValue: "FALSE")!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "FALSE", andExpectedResult: 0.0) + } + + func testArcsin() { + let internTokenList = addOpeningAndClosingBrackets(withTag: "ARCSIN", andValue: "1") + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "arcsin(1)", andExpectedResult: 90.0) + } + + func testArccos() { + let internTokenList = addOpeningAndClosingBrackets(withTag: "ARCCOS", andValue: "0") + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "arccos(0)", andExpectedResult: 90.0) + } + + func testArctan() { + let internTokenList = addOpeningAndClosingBrackets(withTag: "ARCTAN", andValue: "1") + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "arctan(1)", andExpectedResult: 45.0) + } + + func testMax() { + let internTokenList = [InternToken(type: TOKEN_TYPE_FUNCTION_NAME, andValue: "MAX")!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_OPEN)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "3")!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETER_DELIMITER)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "4")!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE)!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "max(3,4)", andExpectedResult: 4.0) + } + + func testMin() { + let internTokenList = [InternToken(type: TOKEN_TYPE_FUNCTION_NAME, andValue: "MIN")!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_OPEN)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "3")!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETER_DELIMITER)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "4")!, + InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE)!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "min(3,4)", andExpectedResult: 3.0) + } + + func addOpeningAndClosingBrackets(withTag tag: String, andValue value: String) -> [InternToken] { + var internTokenList = [InternToken]() + internTokenList.append(InternToken(type: TOKEN_TYPE_FUNCTION_NAME, andValue: tag)) + internTokenList.append(InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_OPEN)) + internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: value)) + internTokenList.append(InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE)) + return internTokenList + } +} diff --git a/src/CattyTests/Formula/FormulaParserOperatorsTest.m b/src/CattyTests/Formula/FormulaParserOperatorsTest.m deleted file mode 100644 index 87365bb78b..0000000000 --- a/src/CattyTests/Formula/FormulaParserOperatorsTest.m +++ /dev/null @@ -1,500 +0,0 @@ -/** - * Copyright (C) 2010-2023 The Catrobat Team - * (http://developer.catrobat.org/credits) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * An additional term exception under section 7 of the GNU Affero - * General Public License, version 3, is available at - * (http://developer.catrobat.org/license_additional_term) - * - * This program 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. - */ - -#import -#import -#import "InternFormulaUtils.h" -#import "InternFormula.h" -#import "Pocket_Code-Swift.h" - -@interface FormulaParserOperatorsTest : XCTestCase -@property (nonatomic, strong) FormulaManager* formulaManager; -@property (nonatomic, strong) id interpreter; -@end - -@implementation FormulaParserOperatorsTest - -- (void)setUp { - [super setUp]; - self.formulaManager = [[FormulaManager alloc] initWithStageSize:[Util screenSize:true] andLandscapeMode: false]; - self.interpreter = (id)self.formulaManager; -} - -- (NSMutableArray *)buildBinaryOperator:(InternTokenType)firstTokenType - firstValue:(NSString *)firstValue - withOperator:(NSString*)operatorTag - secondTokenType:(InternTokenType)secondTokenType - secondValue:(NSString *)secondValue -{ - NSMutableArray *internTokens = [[NSMutableArray alloc] init]; - [internTokens addObject:[[InternToken alloc] initWithType:firstTokenType AndValue:firstValue]]; - [internTokens addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_OPERATOR AndValue:operatorTag]]; - [internTokens addObject:[[InternToken alloc] initWithType:secondTokenType AndValue:secondValue]]; - - return internTokens; -} - -- (NSMutableArray *)mergeOperatorLists:(NSMutableArray *)firstList - withOperator:(NSString*)operatorTag - andSecondList:(NSMutableArray *)secondList -{ - [firstList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_OPERATOR AndValue:operatorTag]]; - [firstList addObjectsFromArray:secondList]; - - return firstList; -} - -- (NSMutableArray *)appendOperationToList:(NSMutableArray *)internTokenList - withOperator:(NSString*)operatorTag - andTokenType:(InternTokenType)tokenType - withValue:(NSString *)value -{ - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_OPERATOR AndValue:operatorTag]]; - [internTokenList addObject:[[InternToken alloc] initWithType:tokenType AndValue:value]]; - - return internTokenList; -} - -- (void)binaryOperatorTest:(NSMutableArray *)internTokens withExpectedResult:(NSString *)result -{ - InternFormulaParser *parser = [[InternFormulaParser alloc] initWithTokens:internTokens andFormulaManager:self.formulaManager]; - FormulaElement *parseTree = [parser parseFormulaForSpriteObject:nil]; - XCTAssertNotNil(parseTree, @"Formula is not parsed correctly!"); - - Formula *formula = [[Formula alloc] initWithFormulaElement:parseTree]; - XCTAssertEqual([self.interpreter interpretInteger:formula forSpriteObject:[[SpriteObject alloc] init]], [result intValue], @"Formula interpretation is not as expected!"); -} - -- (void)testOperatorChain -{ - NSMutableArray *firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"1" withOperator:PlusOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"2"]; - firstTerm = [self appendOperationToList:firstTerm withOperator:MultOperator.tag andTokenType:TOKEN_TYPE_NUMBER withValue:@"3"]; - NSMutableArray *secontTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"2" withOperator:PlusOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"1"]; - firstTerm = [self mergeOperatorLists:firstTerm withOperator:MultOperator.tag andSecondList:secontTerm]; - - [self binaryOperatorTest:firstTerm withExpectedResult:@"14"]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"1" withOperator:PlusOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"2"]; - secontTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"3" withOperator:MultOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"2"]; - firstTerm = [self mergeOperatorLists:firstTerm withOperator:MultOperator.tag andSecondList:secontTerm]; - - [self binaryOperatorTest:firstTerm withExpectedResult:@"13"]; - -} - -- (void)testOperatorLeftBinding -{ - NSMutableArray *firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"5" withOperator:MinusOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"4"]; - [self appendOperationToList:firstTerm withOperator:MinusOperator.tag andTokenType:TOKEN_TYPE_NUMBER withValue:@"1"]; - - [self binaryOperatorTest:firstTerm withExpectedResult:@"0"]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"100" withOperator:DivideOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"10"]; - [self appendOperationToList:firstTerm withOperator:DivideOperator.tag andTokenType:TOKEN_TYPE_NUMBER withValue:@"10"]; - - [self binaryOperatorTest:firstTerm withExpectedResult:@"1"]; -} - -- (void)testOperatorPriority -{ - NSMutableArray *firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"1" withOperator:MinusOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"2"]; - [self appendOperationToList:firstTerm withOperator:MultOperator.tag andTokenType:TOKEN_TYPE_NUMBER withValue:@"2"]; - - [self binaryOperatorTest:firstTerm withExpectedResult:@"-3"]; -} - -- (void)testUnaryMinus -{ - - NSMutableArray *internTokenList = [[NSMutableArray alloc]init]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_OPERATOR AndValue:MinusOperator.tag]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:@"42.42"]]; - - InternFormulaParser *internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - FormulaElement *parseTree = [internParser parseFormulaForSpriteObject:nil]; - XCTAssertNotNil(parseTree, @"Formula is not parsed correctly: - 42.42"); - - Formula *formula = [[Formula alloc] initWithFormulaElement:parseTree]; - XCTAssertEqual([self.interpreter interpretDouble:formula forSpriteObject:[[SpriteObject alloc] init]], -42.42, @"Formula interpretation is not as expected"); -} - -- (void)testGreaterThan -{ - NSMutableArray *firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"2" withOperator:GreaterThanOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"1"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"1"]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"1" withOperator:GreaterThanOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"1"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"0"]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"1" withOperator:GreaterThanOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"2"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"0"]; - - NSMutableArray *secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"2" withOperator:GreaterThanOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"1"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"1"]; - - secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"1" withOperator:GreaterThanOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"1"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"0"]; - - secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"1" withOperator:GreaterThanOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"2"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"0"]; - -} - -- (void)testGreaterOrEqualThan -{ - NSMutableArray *firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"2" withOperator:GreaterOrEqualOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"1"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"1"]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"1" withOperator:GreaterOrEqualOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"1"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"1"]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"1" withOperator:GreaterOrEqualOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"2"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"0"]; - - NSMutableArray *secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"2" withOperator:GreaterOrEqualOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"1"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"1"]; - - secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"1" withOperator:GreaterOrEqualOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"1"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"1"]; - - secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"1" withOperator:GreaterOrEqualOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"2"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"0"]; - -} - -- (void)testSmallerThan -{ - NSMutableArray *firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"2" withOperator:SmallerThanOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"1"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"0"]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"1" withOperator:SmallerThanOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"1"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"0"]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"1" withOperator:SmallerThanOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"2"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"1"]; - - NSMutableArray *secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"2" withOperator:SmallerThanOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"1"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"0"]; - - secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"1" withOperator:SmallerThanOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"1"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"0"]; - - secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"1" withOperator:SmallerThanOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"2"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"1"]; -} - -- (void)testSmallerOrEqualThan -{ - NSMutableArray *firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"2" withOperator:SmallerOrEqualOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"1"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"0"]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"1" withOperator:SmallerOrEqualOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"1"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"1"]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"1" withOperator:SmallerOrEqualOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"2"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"1"]; - - NSMutableArray *secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"2" withOperator:SmallerOrEqualOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"1"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"0"]; - - secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"1" withOperator:SmallerOrEqualOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"1"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"1"]; - - secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"1" withOperator:SmallerOrEqualOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"2"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"1"]; -} - -- (void)testEqual -{ - NSMutableArray *firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"1" withOperator:EqualOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"1"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"1"]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"1" withOperator:EqualOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"5"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"0"]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"1" withOperator:EqualOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"1.0"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"1"]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"1.0" withOperator:EqualOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"1"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"1"]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"1.0" withOperator:EqualOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"1.9"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"0"]; - - NSMutableArray *secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"equalString" withOperator:EqualOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"equalString"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"1"]; - - secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"1" withOperator:EqualOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"1.0"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"1"]; - - secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"1" withOperator:EqualOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"1.0"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"1"]; - - secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"!`\"§$%&/()=?" withOperator:EqualOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"!`\"§$%&/()=????"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"0"]; - - secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"555.555" withOperator:EqualOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"055.77.77"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"0"]; -} - -- (void)testNotEqual -{ - NSMutableArray *firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"1" withOperator:NotEqualOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"1"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"0"]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"1" withOperator:NotEqualOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"5"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"1"]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"1" withOperator:NotEqualOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"1.0"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"0"]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"1.0" withOperator:NotEqualOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"1"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"0"]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"1.0" withOperator:NotEqualOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"1.9"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"1"]; - - NSMutableArray *secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"equalString" withOperator:NotEqualOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"equalString"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"0"]; - - secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"1" withOperator:NotEqualOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"1.0"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"0"]; - - secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"!`\"§$%&/()=?" withOperator:NotEqualOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"!`\"§$%&/()=????"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"1"]; - - secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"555.555" withOperator:NotEqualOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"055.77.77"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"1"]; - - secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"1,555.555" withOperator:EqualOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"1555.555"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"0"]; -} - -- (void)testNot -{ - NSMutableArray *internTokenList = [[NSMutableArray alloc]init]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_OPERATOR AndValue:NotOperator.tag]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:@"1"]]; - - InternFormulaParser *internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - FormulaElement *parseTree = [internParser parseFormulaForSpriteObject:nil]; - XCTAssertNotNil(parseTree, @"Formula is not parsed correctly!"); - - Formula *formula = [[Formula alloc] initWithFormulaElement:parseTree]; - XCTAssertEqual(0.0, [self.interpreter interpretDouble:formula forSpriteObject:[[SpriteObject alloc] init]]); - - internTokenList = [[NSMutableArray alloc]init]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_OPERATOR AndValue:NotOperator.tag]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_NUMBER AndValue:@"0"]]; - - internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - parseTree = [internParser parseFormulaForSpriteObject:nil]; - XCTAssertNotNil(parseTree, @"Formula is not parsed correctly!"); - - formula = [[Formula alloc] initWithFormulaElement:parseTree]; - XCTAssertEqual([self.interpreter interpretDouble:formula forSpriteObject:[[SpriteObject alloc] init]], 1.0); - - internTokenList = [[NSMutableArray alloc]init]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_OPERATOR AndValue:NotOperator.tag]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_STRING AndValue:@"1"]]; - - internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - parseTree = [internParser parseFormulaForSpriteObject:nil]; - XCTAssertNotNil(parseTree, @"Formula is not parsed correctly!"); - - formula = [[Formula alloc] initWithFormulaElement:parseTree]; - XCTAssertEqual(0.0, [self.interpreter interpretDouble:formula forSpriteObject:[[SpriteObject alloc] init]]); - - internTokenList = [[NSMutableArray alloc]init]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_OPERATOR AndValue:NotOperator.tag]]; - [internTokenList addObject:[[InternToken alloc] initWithType:TOKEN_TYPE_STRING AndValue:@"0"]]; - - internParser = [[InternFormulaParser alloc] initWithTokens:internTokenList andFormulaManager:self.formulaManager]; - parseTree = [internParser parseFormulaForSpriteObject:nil]; - XCTAssertNotNil(parseTree, @"Formula is not parsed correctly!"); - - formula = [[Formula alloc] initWithFormulaElement:parseTree]; - XCTAssertEqual(1.0, [self.interpreter interpretDouble:formula forSpriteObject:[[SpriteObject alloc] init]]); -} - -- (void)testAnd -{ - NSMutableArray *firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"0" withOperator:AndOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"0"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"0"]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"1" withOperator:AndOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"0"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"0"]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"1" withOperator:AndOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"1"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"1"]; - - - NSMutableArray *secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"0" withOperator:AndOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"0"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"0"]; - - secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"0" withOperator:AndOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"1"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"0"]; - - secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"1" withOperator:AndOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"1"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"1"]; - - - secondTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"0" withOperator:AndOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"0"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"0"]; - - secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"1" withOperator:AndOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"0"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"0"]; -} - -- (void)testOr -{ - NSMutableArray *firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"0" withOperator:OrOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"0"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"0"]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"1" withOperator:OrOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"0"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"1"]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"1" withOperator:OrOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"1"]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"1"]; - - - NSMutableArray *secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"0" withOperator:OrOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"0"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"0"]; - - secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"0" withOperator:OrOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"1"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"1"]; - - secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"1" withOperator:OrOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"1"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"1"]; - - - secondTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:@"0" withOperator:OrOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:@"0"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"0"]; - - secondTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:@"1" withOperator:OrOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:@"0"]; - [self binaryOperatorTest:secondTerm withExpectedResult:@"1"]; -} - -- (void)testPlus -{ - NSString *firstOperand = @"1.3"; - NSString *secondOperand = @"3"; - NSString *result = @"4.3"; - - NSMutableArray *firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:firstOperand withOperator:PlusOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:secondOperand]; - [self binaryOperatorTest:firstTerm withExpectedResult:result]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:firstOperand withOperator:PlusOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:secondOperand]; - [self binaryOperatorTest:firstTerm withExpectedResult:result]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:firstOperand withOperator:PlusOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:secondOperand]; - [self binaryOperatorTest:firstTerm withExpectedResult:result]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:firstOperand withOperator:PlusOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:secondOperand]; - [self binaryOperatorTest:firstTerm withExpectedResult:result]; - - firstOperand = @"NotANumber"; - secondOperand = @"3.14"; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:firstOperand withOperator:PlusOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:secondOperand]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"NaN"]; -} - -- (void)testDivision -{ - NSString *firstOperand = @"9.0"; - NSString *secondOperand = @"2"; - NSString *result = @"4.5"; - - - NSMutableArray *firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:firstOperand withOperator:DivideOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:secondOperand]; - [self binaryOperatorTest:firstTerm withExpectedResult:result]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:firstOperand withOperator:DivideOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:secondOperand]; - [self binaryOperatorTest:firstTerm withExpectedResult:result]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:firstOperand withOperator:DivideOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:secondOperand]; - [self binaryOperatorTest:firstTerm withExpectedResult:result]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:firstOperand withOperator:DivideOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:secondOperand]; - [self binaryOperatorTest:firstTerm withExpectedResult:result]; - - firstOperand = @"NotANumber"; - secondOperand = @"3.14"; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:firstOperand withOperator:DivideOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:secondOperand]; - [self binaryOperatorTest:firstTerm withExpectedResult:nil]; -} - - -- (void)testMultiplication -{ - NSString *firstOperand = @"9.0"; - NSString *secondOperand = @"2"; - NSString *result = @"18.0"; - - - NSMutableArray *firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:firstOperand withOperator:MultOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:secondOperand]; - [self binaryOperatorTest:firstTerm withExpectedResult:result]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:firstOperand withOperator:MultOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:secondOperand]; - [self binaryOperatorTest:firstTerm withExpectedResult:result]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:firstOperand withOperator:MultOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:secondOperand]; - [self binaryOperatorTest:firstTerm withExpectedResult:result]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:firstOperand withOperator:MultOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:secondOperand]; - [self binaryOperatorTest:firstTerm withExpectedResult:result]; - - firstOperand = @"NotANumber"; - secondOperand = @"3.14"; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:firstOperand withOperator:MultOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:secondOperand]; - [self binaryOperatorTest:firstTerm withExpectedResult:nil]; -} - -- (void)testMinus -{ - NSString *firstOperand = @"9.0"; - NSString *secondOperand = @"2"; - NSString *result = @"7.0"; - - NSMutableArray *firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:firstOperand withOperator:MinusOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:secondOperand]; - [self binaryOperatorTest:firstTerm withExpectedResult:result]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:firstOperand withOperator:MinusOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:secondOperand]; - [self binaryOperatorTest:firstTerm withExpectedResult:result]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_NUMBER firstValue:firstOperand withOperator:MinusOperator.tag secondTokenType:TOKEN_TYPE_STRING secondValue:secondOperand]; - [self binaryOperatorTest:firstTerm withExpectedResult:result]; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:firstOperand withOperator:MinusOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:secondOperand]; - [self binaryOperatorTest:firstTerm withExpectedResult:result]; - - firstOperand = @"NotANumber"; - secondOperand = @"3.14"; - - firstTerm = [self buildBinaryOperator:TOKEN_TYPE_STRING firstValue:firstOperand withOperator:MinusOperator.tag secondTokenType:TOKEN_TYPE_NUMBER secondValue:secondOperand]; - [self binaryOperatorTest:firstTerm withExpectedResult:@"NaN"]; -} - -@end diff --git a/src/CattyTests/Formula/FormulaParserOperatorsTest.swift b/src/CattyTests/Formula/FormulaParserOperatorsTest.swift new file mode 100644 index 0000000000..3b14eede31 --- /dev/null +++ b/src/CattyTests/Formula/FormulaParserOperatorsTest.swift @@ -0,0 +1,459 @@ +/** + * Copyright (C) 2010-2023 The Catrobat Team + * (http://developer.catrobat.org/credits) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * An additional term exception under section 7 of the GNU Affero + * General Public License, version 3, is available at + * (http://developer.catrobat.org/license_additional_term) + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ + +import XCTest + +@testable import Pocket_Code + +final class FormulaParserOperatorsTest: XCTestCase { + + var formulaTestHelper: FormulaTestHelper! + + override func setUp() { + super.setUp() + formulaTestHelper = FormulaTestHelper() + } + + func testOperatorChain() { + var firstTerm = [InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")!, + InternToken(type: TOKEN_TYPE_OPERATOR, andValue: PlusOperator.tag)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2")!] + var secondTerm = [InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2")!, + InternToken(type: TOKEN_TYPE_OPERATOR, andValue: PlusOperator.tag)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")!] + + firstTerm = FormulaTestHelper.appendOperationToList(internTokenList: firstTerm, withOperator: MultOperator.tag, andTokenType: TOKEN_TYPE_NUMBER, withValue: "3") + firstTerm = FormulaTestHelper.mergeOperatorLists(firstList: firstTerm, withOperator: MultOperator.tag, andSecondList: secondTerm) + formulaTestHelper.interpretValidFormula(with: firstTerm, description: "1 + 2 * 3 * 2 + 1", andExpectedResult: 14) + + firstTerm = [InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")!, + InternToken(type: TOKEN_TYPE_OPERATOR, andValue: PlusOperator.tag)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2")!] + secondTerm = [InternToken(type: TOKEN_TYPE_NUMBER, andValue: "3")!, + InternToken(type: TOKEN_TYPE_OPERATOR, andValue: MultOperator.tag)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2")!] + firstTerm = FormulaTestHelper.mergeOperatorLists(firstList: firstTerm, withOperator: MultOperator.tag, andSecondList: secondTerm) + formulaTestHelper.interpretValidFormula(with: firstTerm, description: "1 + 2 * 3 * 2", andExpectedResult: 13) + } + + func testOperatorLeftBinding() { + var firstTerm = [InternToken(type: TOKEN_TYPE_NUMBER, andValue: "5")!, + InternToken(type: TOKEN_TYPE_OPERATOR, andValue: MinusOperator.tag)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "4")!] + firstTerm = FormulaTestHelper.appendOperationToList(internTokenList: firstTerm, withOperator: MinusOperator.tag, andTokenType: TOKEN_TYPE_NUMBER, withValue: "1") + formulaTestHelper.interpretValidFormula(with: firstTerm, description: "5 - 4 - 1", andExpectedResult: 0) + + firstTerm = [InternToken(type: TOKEN_TYPE_NUMBER, andValue: "100")!, + InternToken(type: TOKEN_TYPE_OPERATOR, andValue: DivideOperator.tag)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "10")!] + firstTerm = FormulaTestHelper.appendOperationToList(internTokenList: firstTerm, withOperator: DivideOperator.tag, andTokenType: TOKEN_TYPE_NUMBER, withValue: "10") + formulaTestHelper.interpretValidFormula(with: firstTerm, description: "100 % 10 % 10", andExpectedResult: 1) + } + + func testOperatorPriority() { + var firstTerm = [InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")!, + InternToken(type: TOKEN_TYPE_OPERATOR, andValue: MinusOperator.tag)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2")!] + firstTerm = FormulaTestHelper.appendOperationToList(internTokenList: firstTerm, withOperator: MultOperator.tag, andTokenType: TOKEN_TYPE_NUMBER, withValue: "2") + formulaTestHelper.interpretValidFormula(with: firstTerm, description: "1 - 2 - 2", andExpectedResult: -3) + } + + func testUnaryMinus() { + let internTokenList = [InternToken(type: TOKEN_TYPE_OPERATOR, andValue: MinusOperator.tag)!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "42.42")!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "-42.42", andExpectedResult: -42.42) + } + + func testGreaterThan() { + let tokenGreaterThan = InternToken(type: TOKEN_TYPE_OPERATOR, andValue: GreaterThanOperator.tag) + let tokenNumber1 = InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1") + let tokenNumber2 = InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2") + let tokenString1 = InternToken(type: TOKEN_TYPE_STRING, andValue: "1") + let tokenString2 = InternToken(type: TOKEN_TYPE_STRING, andValue: "2") + + var internTokenList = [tokenNumber2!, tokenGreaterThan!, tokenNumber1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "2 > 1", andExpectedResult: true) + + internTokenList = [tokenNumber1!, tokenGreaterThan!, tokenNumber1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 > 1", andExpectedResult: false) + + internTokenList = [tokenNumber1!, tokenGreaterThan!, tokenNumber2!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 > 2", andExpectedResult: false) + + internTokenList = [tokenString2!, tokenGreaterThan!, tokenString1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "2 > 1", andExpectedResult: true) + + internTokenList = [tokenString1!, tokenGreaterThan!, tokenString1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 > 1", andExpectedResult: false) + + internTokenList = [tokenString1!, tokenGreaterThan!, tokenString2!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 > 2", andExpectedResult: false) + } + + func testGreaterOrEqualThan() { + let tokenGreaterOrEqual = InternToken(type: TOKEN_TYPE_OPERATOR, andValue: GreaterOrEqualOperator.tag) + let tokenNumber1 = InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1") + let tokenNumber2 = InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2") + let tokenString1 = InternToken(type: TOKEN_TYPE_STRING, andValue: "1") + let tokenString2 = InternToken(type: TOKEN_TYPE_STRING, andValue: "2") + + var internTokenList = [tokenNumber2!, tokenGreaterOrEqual!, tokenNumber1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 >= 2", andExpectedResult: true) + + internTokenList = [tokenNumber1!, tokenGreaterOrEqual!, tokenNumber1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 >= 1", andExpectedResult: true) + + internTokenList = [tokenNumber1!, tokenGreaterOrEqual!, tokenNumber2!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 >= 2", andExpectedResult: false) + + internTokenList = [tokenString2!, tokenGreaterOrEqual!, tokenString1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "2 >= 1", andExpectedResult: true) + + internTokenList = [tokenString1!, tokenGreaterOrEqual!, tokenString1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 >= 1", andExpectedResult: true) + + internTokenList = [tokenString1!, tokenGreaterOrEqual!, tokenString2!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 >= 2", andExpectedResult: false) + } + + func testSmallerThan() { + let tokenSmallerThan = InternToken(type: TOKEN_TYPE_OPERATOR, andValue: SmallerThanOperator.tag) + let tokenNumber1 = InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1") + let tokenNumber2 = InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2") + let tokenString1 = InternToken(type: TOKEN_TYPE_STRING, andValue: "1") + let tokenString2 = InternToken(type: TOKEN_TYPE_STRING, andValue: "2") + + var internTokenList = [tokenNumber2!, tokenSmallerThan!, tokenNumber1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "2 < 1", andExpectedResult: false) + + internTokenList = [tokenNumber1!, tokenSmallerThan!, tokenNumber1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 < 1", andExpectedResult: false) + + internTokenList = [tokenNumber1!, tokenSmallerThan!, tokenNumber2!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 > 2", andExpectedResult: true) + + internTokenList = [tokenString2!, tokenSmallerThan!, tokenString1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "2 > 1", andExpectedResult: false) + + internTokenList = [tokenString1!, tokenSmallerThan!, tokenString1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 > 1", andExpectedResult: false) + + internTokenList = [tokenString1!, tokenSmallerThan!, tokenString2!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 > 2", andExpectedResult: true) + } + + func testSmallerOrEqualThan() { + let tokenSmallerOrEqual = InternToken(type: TOKEN_TYPE_OPERATOR, andValue: SmallerOrEqualOperator.tag) + let tokenNumber1 = InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1") + let tokenNumber2 = InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2") + let tokenString1 = InternToken(type: TOKEN_TYPE_STRING, andValue: "1") + let tokenString2 = InternToken(type: TOKEN_TYPE_STRING, andValue: "2") + + var internTokenList = [tokenNumber2!, tokenSmallerOrEqual!, tokenNumber1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "2 <= 1", andExpectedResult: false) + + internTokenList = [tokenNumber1!, tokenSmallerOrEqual!, tokenNumber1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 <= 1", andExpectedResult: true) + + internTokenList = [tokenNumber1!, tokenSmallerOrEqual!, tokenNumber2!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 <= 2", andExpectedResult: true) + + internTokenList = [tokenString2!, tokenSmallerOrEqual!, tokenString1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "2 <= 1", andExpectedResult: false) + + internTokenList = [tokenString1!, tokenSmallerOrEqual!, tokenString1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 <= 1", andExpectedResult: true) + + internTokenList = [tokenString1!, tokenSmallerOrEqual!, tokenString2!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 <= 2", andExpectedResult: true) + } + + func testEqual() { + let tokenEqual = InternToken(type: TOKEN_TYPE_OPERATOR, andValue: EqualOperator.tag) + let tokenNumber1 = InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1") + let tokenString1 = InternToken(type: TOKEN_TYPE_STRING, andValue: "1") + let tokenString10 = InternToken(type: TOKEN_TYPE_STRING, andValue: "1.0") + + var internTokenList = [tokenNumber1!, tokenEqual!, tokenNumber1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 == 1", andExpectedResult: true) + + internTokenList = [tokenNumber1!, tokenEqual!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2")!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 == 2", andExpectedResult: false) + + internTokenList = [tokenNumber1!, tokenEqual!, tokenString10!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 == 1.0", andExpectedResult: true) + + internTokenList = [tokenString10!, tokenEqual!, tokenNumber1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1.0 == 1", andExpectedResult: true) + + internTokenList = [tokenString10!, tokenEqual!, + InternToken(type: TOKEN_TYPE_STRING, andValue: "1.9")!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1.0 == 1.9", andExpectedResult: false) + + internTokenList = [tokenString1!, tokenEqual!, tokenString10!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 == 1.0", andExpectedResult: true) + + internTokenList = [tokenString1!, tokenEqual!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1.0")!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 == 1.0", andExpectedResult: true) + + internTokenList = [InternToken(type: TOKEN_TYPE_STRING, andValue: "equalString")!, tokenEqual!, + InternToken(type: TOKEN_TYPE_STRING, andValue: "equalString")!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "equalString == equalString", andExpectedResult: true) + + internTokenList = [InternToken(type: TOKEN_TYPE_STRING, andValue: "!`\"§$%&/()=?")!, tokenEqual!, + InternToken(type: TOKEN_TYPE_STRING, andValue: "!`\"§$%&/()=????")!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "!`\"§$%&/()=? == !`\"§$%&/()=????", andExpectedResult: false) + + internTokenList = [InternToken(type: TOKEN_TYPE_STRING, andValue: "555.555")!, tokenEqual!, + InternToken(type: TOKEN_TYPE_STRING, andValue: "055.77.77")!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "555.555 == 055.77.77", andExpectedResult: false) + } + + func testNotEqual() { + let tokenNotEqual = InternToken(type: TOKEN_TYPE_OPERATOR, andValue: NotEqualOperator.tag) + let tokenNumber1 = InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1") + let tokenString1 = InternToken(type: TOKEN_TYPE_STRING, andValue: "1") + let tokenString10 = InternToken(type: TOKEN_TYPE_STRING, andValue: "1.0") + + var internTokenList = [tokenNumber1!, tokenNotEqual!, tokenNumber1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 != 1", andExpectedResult: false) + + internTokenList = [tokenNumber1!, tokenNotEqual!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2")!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 != 2", andExpectedResult: true) + + internTokenList = [tokenNumber1!, tokenNotEqual!, tokenString10!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 != 1.0", andExpectedResult: false) + + internTokenList = [tokenString10!, tokenNotEqual!, tokenNumber1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1.0 != 1", andExpectedResult: false) + + internTokenList = [tokenString10!, tokenNotEqual!, + InternToken(type: TOKEN_TYPE_STRING, andValue: "1.9")!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1.0 != 1.9", andExpectedResult: true) + + internTokenList = [tokenString1!, tokenNotEqual!, tokenString10!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 != 1.0", andExpectedResult: false) + + internTokenList = [tokenString1!, tokenNotEqual!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1.0")!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 != 1.0", andExpectedResult: false) + + internTokenList = [InternToken(type: TOKEN_TYPE_STRING, andValue: "equalString")!, tokenNotEqual!, + InternToken(type: TOKEN_TYPE_STRING, andValue: "equalString")!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "equalString != equalString", andExpectedResult: false) + + internTokenList = [InternToken(type: TOKEN_TYPE_STRING, andValue: "!`\"§$%&/()=?")!, tokenNotEqual!, + InternToken(type: TOKEN_TYPE_STRING, andValue: "!`\"§$%&/()=????")!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "!`\"§$%&/()=? != !`\"§$%&/()=????", andExpectedResult: true) + + internTokenList = [InternToken(type: TOKEN_TYPE_STRING, andValue: "555.555")!, tokenNotEqual!, + InternToken(type: TOKEN_TYPE_STRING, andValue: "055.77.77")!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "555.555 != 055.77.77", andExpectedResult: true) + } + + func testNot() { + let tokenNot = InternToken(type: TOKEN_TYPE_OPERATOR, andValue: NotOperator.tag) + let tokenNumber1 = InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1") + let tokenNumber0 = InternToken(type: TOKEN_TYPE_NUMBER, andValue: "0") + let tokenString1 = InternToken(type: TOKEN_TYPE_STRING, andValue: "1") + let tokenString0 = InternToken(type: TOKEN_TYPE_STRING, andValue: "0") + + var internTokenList = [tokenNot!, tokenNumber1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "!1", andExpectedResult: false) + + internTokenList = [tokenNot!, tokenNumber0!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "!0", andExpectedResult: true) + + internTokenList = [tokenNot!, tokenString1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "!1", andExpectedResult: false) + + internTokenList = [tokenNot!, tokenString0!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "!0", andExpectedResult: true) + } + + func testAnd() { + let tokenAnd = InternToken(type: TOKEN_TYPE_OPERATOR, andValue: AndOperator.tag) + let tokenNumber0 = InternToken(type: TOKEN_TYPE_NUMBER, andValue: "0") + let tokenNumber1 = InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1") + let tokenString0 = InternToken(type: TOKEN_TYPE_STRING, andValue: "0") + let tokenString1 = InternToken(type: TOKEN_TYPE_STRING, andValue: "1") + + var internTokenList = [tokenNumber0!, tokenAnd!, tokenNumber0!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "0 && 0", andExpectedResult: 0) + + internTokenList = [tokenNumber1!, tokenAnd!, tokenNumber0!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 && 0", andExpectedResult: 0) + + internTokenList = [tokenNumber1!, tokenAnd!, tokenNumber1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 && 1", andExpectedResult: 1) + + internTokenList = [tokenString0!, tokenAnd!, tokenString0!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "0 && 0", andExpectedResult: 0) + + internTokenList = [tokenString0!, tokenAnd!, tokenString1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "0 && 1", andExpectedResult: 0) + + internTokenList = [tokenString1!, tokenAnd!, tokenString1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 && 1", andExpectedResult: 1) + + internTokenList = [tokenNumber0!, tokenAnd!, tokenString0!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "0 && 0", andExpectedResult: 0) + + internTokenList = [tokenString1!, tokenAnd!, tokenNumber0!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 && 0", andExpectedResult: 0) + } + + func testOr() { + let tokenOr = InternToken(type: TOKEN_TYPE_OPERATOR, andValue: OrOperator.tag) + let tokenNumber0 = InternToken(type: TOKEN_TYPE_NUMBER, andValue: "0") + let tokenNumber1 = InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1") + let tokenString0 = InternToken(type: TOKEN_TYPE_STRING, andValue: "0") + let tokenString1 = InternToken(type: TOKEN_TYPE_STRING, andValue: "1") + + var internTokenList = [tokenNumber0!, tokenOr!, tokenNumber0!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "0 || 0", andExpectedResult: 0) + + internTokenList = [tokenNumber1!, tokenOr!, tokenNumber0!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 || 0", andExpectedResult: 1) + + internTokenList = [tokenNumber1!, tokenOr!, tokenNumber1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 || 1", andExpectedResult: 1) + + internTokenList = [tokenString0!, tokenOr!, tokenString0!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "0 || 0", andExpectedResult: 0) + + internTokenList = [tokenString0!, tokenOr!, tokenString1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "0 || 1", andExpectedResult: 1) + + internTokenList = [tokenString1!, tokenOr!, tokenString1!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 || 1", andExpectedResult: 1) + + internTokenList = [tokenNumber0!, tokenOr!, tokenString0!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "0 || 0", andExpectedResult: 0) + + internTokenList = [tokenString1!, tokenOr!, tokenNumber0!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 || 0", andExpectedResult: 1) + } + + func testPlus() { + let result = 4.3 + let tokenPlus = InternToken(type: TOKEN_TYPE_OPERATOR, andValue: PlusOperator.tag) + let tokenNumber13 = InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1.3") + let tokenNumber3 = InternToken(type: TOKEN_TYPE_NUMBER, andValue: "3") + let tokenString13 = InternToken(type: TOKEN_TYPE_STRING, andValue: "1.3") + let tokenString3 = InternToken(type: TOKEN_TYPE_STRING, andValue: "3") + + var internTokenList = [tokenNumber13!, tokenPlus!, tokenNumber3!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1.3 + 3", andExpectedResult: result) + + internTokenList = [tokenString13!, tokenPlus!, tokenString3!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1.3 + 3", andExpectedResult: result) + + internTokenList = [tokenNumber13!, tokenPlus!, tokenString3!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1.3 + 3", andExpectedResult: result) + + internTokenList = [tokenString13!, tokenPlus!, tokenNumber3!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1.3 + 3", andExpectedResult: result) + + internTokenList = [InternToken(type: TOKEN_TYPE_STRING, andValue: "NotANumber")!, tokenPlus!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "3.14")!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "NotANumber + 3.14", andExpectedResult: "nan") + } + + func testDivision() { + let result = 4.5 + let tokenDivide = InternToken(type: TOKEN_TYPE_OPERATOR, andValue: DivideOperator.tag) + let tokenNumber9 = InternToken(type: TOKEN_TYPE_NUMBER, andValue: "9.0") + let tokenNumber2 = InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2") + let tokenString9 = InternToken(type: TOKEN_TYPE_STRING, andValue: "9.0") + let tokenString2 = InternToken(type: TOKEN_TYPE_STRING, andValue: "2") + + var internTokenList = [tokenNumber9!, tokenDivide!, tokenNumber2!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "9 / 2", andExpectedResult: result) + + internTokenList = [tokenString9!, tokenDivide!, tokenString2!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "9 / 2", andExpectedResult: result) + + internTokenList = [tokenNumber9!, tokenDivide!, tokenString2!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "9 / 2", andExpectedResult: result) + + internTokenList = [tokenString9!, tokenDivide!, tokenNumber2!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "9 / 2", andExpectedResult: result) + + internTokenList = [InternToken(type: TOKEN_TYPE_STRING, andValue: "NotANumber")!, tokenDivide!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "3.14")!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "NotANumber / 3.14", andExpectedResult: "nan") + } + + func testMultiplication() { + let result = 18 + let tokenMult = InternToken(type: TOKEN_TYPE_OPERATOR, andValue: MultOperator.tag) + let tokenNumber9 = InternToken(type: TOKEN_TYPE_NUMBER, andValue: "9.0") + let tokenNumber2 = InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2") + let tokenString9 = InternToken(type: TOKEN_TYPE_STRING, andValue: "9.0") + let tokenString2 = InternToken(type: TOKEN_TYPE_STRING, andValue: "2") + + var internTokenList = [tokenNumber9!, tokenMult!, tokenNumber2!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "9 * 2", andExpectedResult: result) + + internTokenList = [tokenString9!, tokenMult!, tokenString2!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "9 * 2", andExpectedResult: result) + + internTokenList = [tokenNumber9!, tokenMult!, tokenString2!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "9 * 2", andExpectedResult: result) + + internTokenList = [tokenString9!, tokenMult!, tokenNumber2!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "9 * 2", andExpectedResult: result) + + internTokenList = [InternToken(type: TOKEN_TYPE_STRING, andValue: "NotANumber")!, tokenMult!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "3.14")!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "NotANumber / 3.14", andExpectedResult: "nan") + } + + func testMinus() { + let result = 7 + let tokenMinus = InternToken(type: TOKEN_TYPE_OPERATOR, andValue: MinusOperator.tag) + let tokenNumber9 = InternToken(type: TOKEN_TYPE_NUMBER, andValue: "9.0") + let tokenNumber2 = InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2") + let tokenString9 = InternToken(type: TOKEN_TYPE_STRING, andValue: "9.0") + let tokenString2 = InternToken(type: TOKEN_TYPE_STRING, andValue: "2") + + var internTokenList = [tokenNumber9!, tokenMinus!, tokenNumber2!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "9 - 2", andExpectedResult: result) + + internTokenList = [tokenString9!, tokenMinus!, tokenString2!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "9 - 2", andExpectedResult: result) + + internTokenList = [tokenNumber9!, tokenMinus!, tokenString2!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "9 - 2", andExpectedResult: result) + + internTokenList = [tokenString9!, tokenMinus!, tokenNumber2!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "9 - 2", andExpectedResult: result) + + internTokenList = [InternToken(type: TOKEN_TYPE_STRING, andValue: "NotANumber")!, tokenMinus!, + InternToken(type: TOKEN_TYPE_NUMBER, andValue: "3.14")!] + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "NotANumber - 3.14", andExpectedResult: "nan") + } +} diff --git a/src/CattyTests/Formula/FormulaParserTest.swift b/src/CattyTests/Formula/FormulaParserTest.swift index 9f58afb1bb..44e3d69029 100644 --- a/src/CattyTests/Formula/FormulaParserTest.swift +++ b/src/CattyTests/Formula/FormulaParserTest.swift @@ -26,69 +26,47 @@ import XCTest final class FormulaParserTest: XCTestCase { - var formulaManager: FormulaManager! - var interpreter: FormulaInterpreterProtocol! - var spriteObject: SpriteObject! + var formulaTestHelper: FormulaTestHelper! override func setUp() { super.setUp() - let screenSize = Util.screenSize(true) - formulaManager = FormulaManager(stageSize: screenSize, landscapeMode: false) - interpreter = formulaManager - spriteObject = SpriteObject() - } - - func interpretInvalidFormula(with internTokenList: [InternToken], description: String, andExpectedErrorCode errorCode: Int32) { - let internParser = InternFormulaParser(tokens: internTokenList, andFormulaManager: formulaManager) - let parseTree = internParser?.parseFormula(for: nil) - XCTAssertNil(parseTree, "Parsed invalid formula " + description) - - XCTAssertEqual(errorCode, internParser?.errorTokenIndex, "Invalid error code for formula " + description) - } - - func interpretValidFormula(with internTokenList: [InternToken], description: String, andExpectedResult result: Double) { - let internParser = InternFormulaParser(tokens: internTokenList, andFormulaManager: formulaManager) - let parseTree = internParser?.parseFormula(for: nil) - XCTAssertNotNil(parseTree, "Could not parse formula " + description) - - let formula = Formula(formulaElement: parseTree) - XCTAssertEqual(result, interpreter.interpretDouble(formula!, for: spriteObject), "Invalid result for formula " + description) + formulaTestHelper = FormulaTestHelper() } func testEmptyInput() { let internTokenList = [InternToken]() - interpretInvalidFormula(with: internTokenList, description: "", andExpectedErrorCode: FORMULA_PARSER_NO_INPUT.rawValue) + formulaTestHelper.interpretInvalidFormula(with: internTokenList, description: "", andExpectedErrorCode: FORMULA_PARSER_NO_INPUT.rawValue) } func testInvalidInput() { var internTokenList = [InternToken]() internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "")) - interpretInvalidFormula(with: internTokenList, description: "", andExpectedErrorCode: 0) + formulaTestHelper.interpretInvalidFormula(with: internTokenList, description: "", andExpectedErrorCode: 0) internTokenList.removeAll() internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: ".")) - interpretInvalidFormula(with: internTokenList, description: ".", andExpectedErrorCode: 0) + formulaTestHelper.interpretInvalidFormula(with: internTokenList, description: ".", andExpectedErrorCode: 0) internTokenList.removeAll() internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: ".1")) - interpretInvalidFormula(with: internTokenList, description: ".1", andExpectedErrorCode: 0) + formulaTestHelper.interpretInvalidFormula(with: internTokenList, description: ".1", andExpectedErrorCode: 0) } func testNumbers() { var internTokenList = [InternToken]() internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1.0")) - interpretValidFormula(with: internTokenList, description: "1.0", andExpectedResult: 1.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1.0", andExpectedResult: 1.0) internTokenList.removeAll() internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")) - interpretValidFormula(with: internTokenList, description: "1", andExpectedResult: 1.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1", andExpectedResult: 1.0) } func testUnaryMinus() { var internTokenList = [InternToken]() internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: MinusOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "42.42")) - interpretValidFormula(with: internTokenList, description: "-42.42", andExpectedResult: -42.42) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "-42.42", andExpectedResult: -42.42) } func testGreaterOperators() { @@ -96,25 +74,25 @@ final class FormulaParserTest: XCTestCase { internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2")) internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: GreaterThanOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")) - interpretValidFormula(with: internTokenList, description: "2 > 1", andExpectedResult: 1.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "2 > 1", andExpectedResult: 1.0) internTokenList.removeAll() internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")) internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: GreaterThanOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")) - interpretValidFormula(with: internTokenList, description: "1 > 1", andExpectedResult: 0.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 > 1", andExpectedResult: 0.0) internTokenList.removeAll() internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")) internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: GreaterOrEqualOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")) - interpretValidFormula(with: internTokenList, description: "1 >= 1", andExpectedResult: 1.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 >= 1", andExpectedResult: 1.0) internTokenList.removeAll() internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")) internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: GreaterOrEqualOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2")) - interpretValidFormula(with: internTokenList, description: "1 >= 2", andExpectedResult: 0.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 >= 2", andExpectedResult: 0.0) } func testSmallerOperators() { @@ -122,25 +100,25 @@ final class FormulaParserTest: XCTestCase { internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")) internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: SmallerThanOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2")) - interpretValidFormula(with: internTokenList, description: "1 < 2", andExpectedResult: 1.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 < 2", andExpectedResult: 1.0) internTokenList.removeAll() internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")) internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: SmallerThanOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")) - interpretValidFormula(with: internTokenList, description: "1 < 1", andExpectedResult: 0.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 < 1", andExpectedResult: 0.0) internTokenList.removeAll() internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")) internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: SmallerOrEqualOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")) - interpretValidFormula(with: internTokenList, description: "1 <= 1", andExpectedResult: 1.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 <= 1", andExpectedResult: 1.0) internTokenList.removeAll() internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2")) internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: SmallerOrEqualOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")) - interpretValidFormula(with: internTokenList, description: "2 <= 1", andExpectedResult: 0.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "2 <= 1", andExpectedResult: 0.0) } func testEqualOperators() { @@ -148,25 +126,25 @@ final class FormulaParserTest: XCTestCase { internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")) internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: EqualOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")) - interpretValidFormula(with: internTokenList, description: "1 == 1", andExpectedResult: 1.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 == 1", andExpectedResult: 1.0) internTokenList.removeAll() internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2")) internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: EqualOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")) - interpretValidFormula(with: internTokenList, description: "2 == 1", andExpectedResult: 0.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "2 == 1", andExpectedResult: 0.0) internTokenList.removeAll() internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2")) internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: NotEqualOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")) - interpretValidFormula(with: internTokenList, description: "2 != 1", andExpectedResult: 1.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "2 != 1", andExpectedResult: 1.0) internTokenList.removeAll() internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")) internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: NotEqualOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")) - interpretValidFormula(with: internTokenList, description: "1 != 1", andExpectedResult: 0.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 != 1", andExpectedResult: 0.0) } func testLogicalOperators() { @@ -175,28 +153,28 @@ final class FormulaParserTest: XCTestCase { internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "0")) internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: AndOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")) - interpretValidFormula(with: internTokenList, description: "NOT 0 AND 1", andExpectedResult: 1.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "NOT 0 AND 1", andExpectedResult: 1.0) internTokenList.removeAll() internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: NotOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")) internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: OrOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "0")) - interpretValidFormula(with: internTokenList, description: "NOT 1 OR 0", andExpectedResult: 0.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "NOT 1 OR 0", andExpectedResult: 0.0) internTokenList.removeAll() internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: NotOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "0")) internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: OrOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "0")) - interpretValidFormula(with: internTokenList, description: "NOT 0 OR 0", andExpectedResult: 1.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "NOT 0 OR 0", andExpectedResult: 1.0) internTokenList.removeAll() internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: NotOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "0")) internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: AndOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "0")) - interpretValidFormula(with: internTokenList, description: "NOT 0 AND 0", andExpectedResult: 0.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "NOT 0 AND 0", andExpectedResult: 0.0) } func testOperatorPriority() { @@ -206,7 +184,7 @@ final class FormulaParserTest: XCTestCase { internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2")) internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: MultOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2")) - interpretValidFormula(with: internTokenList, description: "1 - 2 * 2", andExpectedResult: -3.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 - 2 * 2", andExpectedResult: -3.0) } func testOperatorLeftBinding() { @@ -216,7 +194,7 @@ final class FormulaParserTest: XCTestCase { internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "4")) internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: MinusOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")) - interpretValidFormula(with: internTokenList, description: "5 - 4 - 1", andExpectedResult: 0.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "5 - 4 - 1", andExpectedResult: 0.0) internTokenList.removeAll() internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "100")) @@ -224,7 +202,7 @@ final class FormulaParserTest: XCTestCase { internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "10")) internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: DivideOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "10")) - interpretValidFormula(with: internTokenList, description: "100 / 10 / 10", andExpectedResult: 1.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "100 / 10 / 10", andExpectedResult: 1.0) } func testOperatorChain() { @@ -241,7 +219,7 @@ final class FormulaParserTest: XCTestCase { internTokenList.append(InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE)) internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: PlusOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")) - interpretValidFormula(with: internTokenList, description: "(1 + 2 * 3) ^ 2 + 1", andExpectedResult: 50.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "(1 + 2 * 3) ^ 2 + 1", andExpectedResult: 50.0) internTokenList.removeAll() internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "1")) @@ -254,7 +232,7 @@ final class FormulaParserTest: XCTestCase { internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: MultOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2")) internTokenList.append(InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE)) - interpretValidFormula(with: internTokenList, description: "1 + 2 ^ (3 * 2)", andExpectedResult: 65.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "1 + 2 ^ (3 * 2)", andExpectedResult: 65.0) } func testBrackets() { @@ -270,7 +248,7 @@ final class FormulaParserTest: XCTestCase { internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: PlusOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2")) internTokenList.append(InternToken(type: TOKEN_TYPE_BRACKET_CLOSE)) - interpretValidFormula(with: internTokenList, description: "(1 + 2) * (1 + 2)", andExpectedResult: 9.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "(1 + 2) * (1 + 2)", andExpectedResult: 9.0) internTokenList.removeAll() internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: MinusOperator.tag)) @@ -291,7 +269,7 @@ final class FormulaParserTest: XCTestCase { internTokenList.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: MinusOperator.tag)) internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "2")) internTokenList.append(InternToken(type: TOKEN_TYPE_BRACKET_CLOSE)) - interpretValidFormula(with: internTokenList, description: "-(1 ^ 2) - -(-1 - -2)", andExpectedResult: 0.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "-(1 ^ 2) - -(-1 - -2)", andExpectedResult: 0.0) } func testBracketCorrection() { @@ -306,7 +284,7 @@ final class FormulaParserTest: XCTestCase { internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "10")) internTokenList.append(InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE)) internTokenList.append(InternToken(type: TOKEN_TYPE_BRACKET_CLOSE)) - interpretValidFormula(with: internTokenList, description: "abs(2 * (5 - 10))", andExpectedResult: 10.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "abs(2 * (5 - 10))", andExpectedResult: 10.0) internTokenList.removeAll() internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "3")) @@ -319,7 +297,7 @@ final class FormulaParserTest: XCTestCase { internTokenList.append(InternToken(type: TOKEN_TYPE_NUMBER, andValue: "0")) internTokenList.append(InternToken(type: TOKEN_TYPE_BRACKET_CLOSE)) internTokenList.append(InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE)) - interpretValidFormula(with: internTokenList, description: "3 * (2 + cos(0))", andExpectedResult: 9.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "3 * (2 + cos(0))", andExpectedResult: 9.0) internTokenList.removeAll() internTokenList.append(InternToken(type: TOKEN_TYPE_FUNCTION_NAME, andValue: ModFunction.tag)) @@ -340,6 +318,6 @@ final class FormulaParserTest: XCTestCase { internTokenList.append(InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE)) internTokenList.append(InternToken(type: TOKEN_TYPE_FUNCTION_PARAMETERS_BRACKET_CLOSE)) internTokenList.append(InternToken(type: TOKEN_TYPE_BRACKET_CLOSE)) - interpretValidFormula(with: internTokenList, description: "mod(1, mod(1, mod(5, (3))))", andExpectedResult: 0.0) + formulaTestHelper.interpretValidFormula(with: internTokenList, description: "mod(1, mod(1, mod(5, (3))))", andExpectedResult: 0.0) } } diff --git a/src/CattyTests/Formula/FormulaTestHelper.swift b/src/CattyTests/Formula/FormulaTestHelper.swift new file mode 100644 index 0000000000..e0bc740130 --- /dev/null +++ b/src/CattyTests/Formula/FormulaTestHelper.swift @@ -0,0 +1,112 @@ +/** + * Copyright (C) 2010-2023 The Catrobat Team + * (http://developer.catrobat.org/credits) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * An additional term exception under section 7 of the GNU Affero + * General Public License, version 3, is available at + * (http://developer.catrobat.org/license_additional_term) + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ + +import XCTest + +@testable import Pocket_Code + +class FormulaTestHelper { + + var formulaManager: FormulaManager! + var interpreter: FormulaInterpreterProtocol! + var spriteObject: SpriteObject! + + init() { + let screenSize = Util.screenSize(true) + formulaManager = FormulaManager(stageSize: screenSize, landscapeMode: false) + interpreter = formulaManager + spriteObject = SpriteObject() + } + + static func mergeOperatorLists(firstList: [InternToken], withOperator operatorTag: String, andSecondList secondList: [InternToken]) -> [InternToken] { + var result = firstList + result.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: operatorTag)) + result.append(contentsOf: secondList) + return result + } + + static func appendOperationToList(internTokenList: [InternToken], withOperator operatorTag: String, andTokenType tokenType: InternTokenType, withValue value: String) -> [InternToken] { + var result = internTokenList + result.append(InternToken(type: TOKEN_TYPE_OPERATOR, andValue: operatorTag)) + result.append(InternToken(type: tokenType, andValue: value)) + return result + } + + func interpretValidFormula(with internTokens: [InternToken], description: String, andExpectedResult result: T) { + interpretValidFormula(with: internTokens, description: description, andExpectedResult: result, withAccuracy: Optional.none) + } + + func interpretValidFormula(with internTokens: [InternToken], description: String, andExpectedResult result: T, withAccuracy accuracy: U?) { + let parser = InternFormulaParser(tokens: internTokens, andFormulaManager: formulaManager) + let parseTree = parser?.parseFormula(for: nil) + XCTAssertNotNil(parseTree, "Could not parse formula " + description) + let formula = Formula(formulaElement: parseTree)! + + if accuracy != nil { + assertFormulaWithAccuracy(formula: formula, withResult: result, withAccuracy: accuracy) + } else { + assertFormula(formula: formula, withResult: result) + } + } + + private func assertFormula(formula: Formula, withResult result: T) { + let errorMessage = "Formula interpretation is not as expected!" + + switch type(of: result) { + case is Int.Type: + XCTAssertEqual(interpreter.interpretInteger(formula, for: spriteObject), result as! Int, errorMessage) + case is Double.Type: + XCTAssertEqual(interpreter.interpretDouble(formula, for: spriteObject), result as! Double, errorMessage) + case is Float.Type: + XCTAssertEqual(interpreter.interpretFloat(formula, for: spriteObject), result as! Float, errorMessage) + case is String.Type: + XCTAssertEqual(interpreter.interpretString(formula, for: spriteObject), result as! String, errorMessage) + case is Bool.Type: + XCTAssertEqual(interpreter.interpretBool(formula, for: spriteObject), result as! Bool, errorMessage) + default: + XCTAssertEqual(interpreter.interpretString(formula, for: spriteObject), result as! String, errorMessage) + } + } + + private func assertFormulaWithAccuracy(formula: Formula, withResult result: T, withAccuracy accuracy: U) { + let errorMessage = "Formula interpretation is not as expected!" + + switch type(of: result) { + case is Int.Type: + XCTAssertEqual(interpreter.interpretInteger(formula, for: spriteObject), result as! Int, accuracy: accuracy as! Int, errorMessage) + case is Double.Type: + XCTAssertEqual(interpreter.interpretDouble(formula, for: spriteObject), result as! Double, accuracy: accuracy as! Double, errorMessage) + case is Float.Type: + XCTAssertEqual(interpreter.interpretFloat(formula, for: spriteObject), result as! Float, accuracy: accuracy as! Float, errorMessage) + default: + XCTAssertEqual(interpreter.interpretString(formula, for: spriteObject), result as! String, errorMessage) + } + } + + func interpretInvalidFormula(with internTokenList: [InternToken], description: String, andExpectedErrorCode errorCode: Int32) { + let internParser = InternFormulaParser(tokens: internTokenList, andFormulaManager: formulaManager) + let parseTree = internParser?.parseFormula(for: nil) + XCTAssertNil(parseTree, "Parsed invalid formula " + description) + XCTAssertEqual(errorCode, internParser?.errorTokenIndex, "Invalid error code for formula " + description) + } + +}