// // MPExpressionTests.m // MathPad // // Created by Kim Wittenburg on 19.04.14. // Copyright (c) 2014 Kim Wittenburg. All rights reserved. // #import #import "MPExpression.h" #import "MPFunction.h" @interface MPExpressionTests : XCTestCase @end @implementation MPExpressionTests - (void)testInitialization { MPExpression *emptyExpression = [[MPExpression alloc] init]; MPExpression *stringExpression = [[MPExpression alloc] initWithString:@"1234+5678"]; MPExpression *functionExpression = [[MPExpression alloc] initWithFunction:[[MPFunction alloc] init]]; MPExpression *complexExpression = [[MPExpression alloc] initWithSymbols:@[@"1234", [[MPFunction alloc] init], @"17", [[MPFunction alloc] init]]]; XCTAssertEqual([emptyExpression numberOfSymbols], 0); XCTAssertEqual([stringExpression numberOfSymbols], 1); XCTAssertEqual([functionExpression numberOfSymbols], 1); XCTAssertEqual([complexExpression numberOfSymbols], 4); XCTAssertEqualObjects([stringExpression symbolAtIndex:0], @"1234+5678"); XCTAssertEqualObjects([functionExpression symbolAtIndex:0], [[MPFunction alloc] init]); XCTAssertEqualObjects([complexExpression symbolAtIndex:2], @"17"); } - (void)testSubexpressions { MPExpression *testExpression = [MPExpression expressionWithSymbols:@[@"1234", [[MPFunction alloc] init], @"17", [[MPFunction alloc] init]]]; /********** subexpressionFromIndex: **********/ // Test with start index at front MPExpression *subexpression = [testExpression subexpressionFromIndex:0]; XCTAssertEqual([subexpression numberOfSymbols], 4); XCTAssertEqualObjects([subexpression symbolAtIndex:0], @"1234"); // Test with start index in first symbol subexpression = [testExpression subexpressionFromIndex:2]; XCTAssertEqual([subexpression numberOfSymbols], 4); XCTAssertEqualObjects([subexpression symbolAtIndex:0], @"34"); // Test with start index in middle symbol starting with a literal subexpression = [testExpression subexpressionFromIndex:6]; XCTAssertEqual([subexpression numberOfSymbols], 2); XCTAssertEqualObjects([subexpression symbolAtIndex:0], @"7"); // Test with start index in middle symbol starting with a function subexpression = [testExpression subexpressionFromIndex:4]; XCTAssertEqual([subexpression numberOfSymbols], 3); XCTAssertEqualObjects([subexpression symbolAtIndex:0], [[MPFunction alloc] init]); // Test with start index in last symbol subexpression = [testExpression subexpressionFromIndex:7]; XCTAssertEqual([subexpression numberOfSymbols], 1); XCTAssertEqualObjects([subexpression symbolAtIndex:0], [[MPFunction alloc] init]); // Test with start index at end subexpression = [testExpression subexpressionFromIndex:8]; XCTAssertEqual([subexpression numberOfSymbols], 0); /********** subexpressionToIndex: **********/ // Test with end index at front subexpression = [testExpression subexpressionToIndex:0]; XCTAssertEqual([subexpression numberOfSymbols], 0); // Test with end index in first symbol subexpression = [testExpression subexpressionToIndex:2]; XCTAssertEqual([subexpression numberOfSymbols], 1); XCTAssertEqualObjects([subexpression symbolAtIndex:0], @"12"); // Test with end index in middle symbol ending with a literal subexpression = [testExpression subexpressionToIndex:6]; XCTAssertEqual([subexpression numberOfSymbols], 3); XCTAssertEqualObjects([subexpression symbolAtIndex:2], @"1"); // Test with end index in middle symbol ending with a function subexpression = [testExpression subexpressionToIndex:5]; XCTAssertEqual([subexpression numberOfSymbols], 2); XCTAssertEqualObjects([subexpression symbolAtIndex:1], [[MPFunction alloc] init]); // Test with end index at end subexpression = [testExpression subexpressionToIndex:8]; XCTAssertEqual([subexpression numberOfSymbols], 4); XCTAssertEqualObjects([subexpression symbolAtIndex:3], [[MPFunction alloc] init]); /********** subexpressionWithRange: **********/ // Test with empty range subexpression = [testExpression subexpressionWithRange:NSMakeRange(4, 0)]; XCTAssertEqual([subexpression numberOfSymbols], 0); // Test with start and end in first symbol subexpression = [testExpression subexpressionWithRange:NSMakeRange(1, 2)]; XCTAssertEqual([subexpression numberOfSymbols], 1); XCTAssertEqualObjects([subexpression symbolAtIndex:0], @"23"); // Test with start in first and end in middle after function subexpression = [testExpression subexpressionWithRange:NSMakeRange(2, 3)]; XCTAssertEqual([subexpression numberOfSymbols], 2); XCTAssertEqualObjects([subexpression symbolAtIndex:0], @"34"); XCTAssertEqualObjects([subexpression symbolAtIndex:1], [[MPFunction alloc] init]); // Test with start in first and end in middle after literal subexpression = [testExpression subexpressionWithRange:NSMakeRange(2, 4)]; XCTAssertEqual([subexpression numberOfSymbols], 3); XCTAssertEqualObjects([subexpression symbolAtIndex:0], @"34"); XCTAssertEqualObjects([subexpression symbolAtIndex:2], @"1"); } - (void)testSubexpressionsIllegalRange { MPExpression *testExpression = [MPExpression expressionWithSymbols:@[@"1234", [[MPFunction alloc] init], @"17", [[MPFunction alloc] init]]]; // Test with start index beyond end @try { [testExpression subexpressionFromIndex:10]; XCTFail(@"Should have raised an exception."); } @catch (NSException *exception) {} // Test with range extending bounds @try { [testExpression subexpressionWithRange:NSMakeRange(5, 10)]; XCTFail(@"Should have raised an exception."); } @catch (NSException *exception) {} } - (void)testEqualExpressions { MPExpression *expression1 = [[MPExpression alloc] initWithString:@"123"]; MPExpression *expression2 = [[MPExpression alloc] initWithString:@"1234"]; MPExpression *expression3 = [[MPExpression alloc] initWithFunction:[[MPFunction alloc] init]]; MPExpression *expression4 = [[MPExpression alloc] initWithSymbols:@[[[MPFunction alloc] init], @"123"]]; MPExpression *expression5 = [[MPExpression alloc] initWithSymbols:@[[[MPFunction alloc] init], @"123"]]; XCTAssertNotEqualObjects(expression1, expression2); XCTAssertNotEqualObjects(expression1, expression3); XCTAssertNotEqualObjects(expression1, expression4); XCTAssertNotEqualObjects(expression3, expression4); XCTAssertEqualObjects(expression4, expression5); } - (void)testAppendSymbols { MPExpression *expression1 = [[MPExpression alloc] initWithString:@"123"]; MPExpression *expression2 = [expression1 expressionByAppendingFunction:[[MPFunction alloc] init]]; MPExpression *expression3 = [[MPExpression alloc] initWithSymbols:@[@"123", [[MPFunction alloc] init]]]; XCTAssertEqualObjects(expression2, expression3); } - (void)testDescription { // Test Simple Expressions MPExpression *testExpression = [[MPExpression alloc] initWithString:@"1234"]; XCTAssertEqualObjects([testExpression description], @"1234"); testExpression = [[MPExpression alloc] initWithFunction:[[MPFunction alloc] init]]; XCTAssertEqualObjects([testExpression description], @"[]"); // Test function after literal without explicit operator testExpression = [[MPExpression alloc] initWithSymbols:@[@"123", [[MPFunction alloc] init]]]; XCTAssertEqualObjects([testExpression description], @"123*[]"); // Test function after literal with explicit operator testExpression = [[MPExpression alloc] initWithSymbols:@[@"123+", [[MPFunction alloc] init]]]; XCTAssertEqualObjects([testExpression description], @"123+[]"); // Test literal after function without explicit operator testExpression = [[MPExpression alloc] initWithSymbols:@[[[MPFunction alloc] init], @"123"]]; XCTAssertEqualObjects([testExpression description], @"[]*123"); // Test literal after function with explicit operator testExpression = [[MPExpression alloc] initWithSymbols:@[[[MPFunction alloc] init], @"-123"]]; XCTAssertEqualObjects([testExpression description], @"[]-123"); // Test function after function without explicit operator testExpression = [[MPExpression alloc] initWithSymbols:@[[[MPFunction alloc] init], [[MPFunction alloc] init]]]; XCTAssertEqualObjects([testExpression description], @"[]*[]"); // Test function after function with explicit operator testExpression = [[MPExpression alloc] initWithSymbols:@[[[MPFunction alloc] init], @"-", [[MPFunction alloc] init]]]; XCTAssertEqualObjects([testExpression description], @"[]-[]"); // Test whitespaces in literal testExpression = [[MPExpression alloc] initWithSymbols:@[@" 123 + ", [[MPFunction alloc] init]]]; XCTAssertEqualObjects([testExpression description], @"123 +[]"); } - (void)testCopying { MPExpression *baseExpression = [[MPExpression alloc] initWithFunction:[[MPFunction alloc] init]]; MPExpression *copy = [baseExpression copy]; XCTAssertNotEqual(copy, baseExpression); XCTAssertNotEqual([baseExpression symbolAtIndex:0], [copy symbolAtIndex:0]); } - (void)testMutableCopying { MPExpression *baseExpression = [[MPExpression alloc] initWithString:@"123"]; MPMutableExpression *expression1 = [baseExpression mutableCopy]; [expression1 appendFunction:[[MPFunction alloc] init]]; MPExpression *expression2 = [[MPExpression alloc] initWithSymbols:@[@"123", [[MPFunction alloc] init]]]; XCTAssertEqualObjects(expression1, expression2); XCTAssertNotEqualObjects(baseExpression, expression1); } // TODO: Test evaluating expressions @end