// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" #include using namespace std; using namespace WEX::Common; using namespace WEX::Logging; using namespace WEX::TestExecution; using namespace CalculationManager; namespace CalculatorUnitTests { class CalcInputTest { TEST_CLASS(CalcInputTest); TEST_CLASS_SETUP(CommonSetup) { m_calcInput = CalcEngine::CalcInput(L'.'); return true; } TEST_METHOD_CLEANUP(Cleanup) { m_calcInput.Clear(); m_calcInput.SetDecimalSymbol(L'.'); return true; } TEST_METHOD(Clear) { m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32); m_calcInput.TryToggleSign(false, L"999"); m_calcInput.TryAddDecimalPt(); m_calcInput.TryAddDigit(2, 10, false, L"999", 64, 32); m_calcInput.TryBeginExponent(); m_calcInput.TryAddDigit(3, 10, false, L"999", 64, 32); VERIFY_ARE_EQUAL(L"-1.2e+3", m_calcInput.ToString(10, false), L"Verify input is correct."); m_calcInput.Clear(); ::Log::Comment(m_calcInput.ToString(10, false).c_str()); VERIFY_ARE_EQUAL(L"0", m_calcInput.ToString(10, false), L"Verify input is 0 after clear."); } TEST_METHOD(TryToggleSignZero) { VERIFY_IS_TRUE(m_calcInput.TryToggleSign(false, L"999"), L"Verify toggling 0 succeeds."); VERIFY_ARE_EQUAL(L"0", m_calcInput.ToString(10, false), L"Verify toggling 0 does not create -0."); } TEST_METHOD(TryToggleSignExponent) { m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32); m_calcInput.TryBeginExponent(); m_calcInput.TryAddDigit(2, 10, false, L"999", 64, 32); VERIFY_IS_TRUE(m_calcInput.TryToggleSign(false, L"999"), L"Verify toggling exponent sign succeeds."); VERIFY_ARE_EQUAL(L"1.e-2", m_calcInput.ToString(10, false), L"Verify toggling exponent sign does not toggle base sign."); VERIFY_IS_TRUE(m_calcInput.TryToggleSign(false, L"999"), L"Verify toggling exponent sign succeeds."); VERIFY_ARE_EQUAL(L"1.e+2", m_calcInput.ToString(10, false), L"Verify toggling negative exponent sign does not toggle base sign."); } TEST_METHOD(TryToggleSignBase) { m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32); VERIFY_IS_TRUE(m_calcInput.TryToggleSign(false, L"999"), L"Verify toggling base sign succeeds."); VERIFY_ARE_EQUAL(L"-1", m_calcInput.ToString(10, false), L"Verify toggling base sign creates negative base."); VERIFY_IS_TRUE(m_calcInput.TryToggleSign(false, L"999"), L"Verify toggling base sign succeeds."); VERIFY_ARE_EQUAL(L"1", m_calcInput.ToString(10, false), L"Verify toggling negative base sign creates positive base."); } TEST_METHOD(TryToggleSignBaseIntegerMode) { m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32); VERIFY_IS_TRUE(m_calcInput.TryToggleSign(true, L"999"), L"Verify toggling base sign in integer mode succeeds."); VERIFY_ARE_EQUAL(L"-1", m_calcInput.ToString(10, false), L"Verify toggling base sign creates negative base."); } TEST_METHOD(TryToggleSignRollover) { m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32); m_calcInput.TryAddDigit(2, 10, false, L"999", 64, 32); VERIFY_IS_TRUE(m_calcInput.TryToggleSign(true, L"127"), L"Verify toggling base sign in integer mode succeeds."); m_calcInput.TryAddDigit(8, 10, false, L"999", 64, 32); VERIFY_IS_FALSE(m_calcInput.TryToggleSign(true, L"127"), L"Verify toggling base sign in integer mode fails on rollover."); VERIFY_ARE_EQUAL(L"-128", m_calcInput.ToString(10, false), L"Verify toggling base sign on rollover does not change value."); } TEST_METHOD(TryAddDigitLeadingZeroes) { VERIFY_IS_TRUE(m_calcInput.TryAddDigit(0, 10, false, L"999", 64, 32), L"Verify TryAddDigit succeeds."); VERIFY_IS_TRUE(m_calcInput.TryAddDigit(0, 10, false, L"999", 64, 32), L"Verify TryAddDigit succeeds."); VERIFY_IS_TRUE(m_calcInput.TryAddDigit(0, 10, false, L"999", 64, 32), L"Verify TryAddDigit succeeds."); VERIFY_ARE_EQUAL(L"0", m_calcInput.ToString(10, false), L"Verify leading zeroes are ignored."); } TEST_METHOD(TryAddDigitMaxCount) { VERIFY_IS_TRUE(m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32), L"Verify TryAddDigit for base with length < maxDigits succeeds."); VERIFY_ARE_EQUAL(L"1", m_calcInput.ToString(10, false), L"Verify adding digit for base with length < maxDigits succeeded."); VERIFY_IS_FALSE(m_calcInput.TryAddDigit(2, 10, false, L"999", 64, 1), L"Verify TryAddDigit for base with length > maxDigits fails."); VERIFY_ARE_EQUAL(L"1", m_calcInput.ToString(10, false), L"Verify digit for base was not added."); m_calcInput.TryBeginExponent(); VERIFY_IS_TRUE(m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32), L"Verify TryAddDigit for exponent with length < maxDigits succeeds."); VERIFY_IS_TRUE(m_calcInput.TryAddDigit(2, 10, false, L"999", 64, 32), L"Verify TryAddDigit for exponent with length < maxDigits succeeds."); VERIFY_IS_TRUE(m_calcInput.TryAddDigit(3, 10, false, L"999", 64, 32), L"Verify TryAddDigit for exponent with length < maxDigits succeeds."); VERIFY_IS_TRUE(m_calcInput.TryAddDigit(4, 10, false, L"999", 64, 32), L"Verify TryAddDigit for exponent with length < maxDigits succeeds."); VERIFY_IS_FALSE(m_calcInput.TryAddDigit(5, 10, false, L"999", 64, 32), L"Verify TryAddDigit for exponent with length > maxDigits fails."); VERIFY_ARE_EQUAL(L"1.e+1234", m_calcInput.ToString(10, false), L"Verify adding digits for exponent with length < maxDigits succeeded."); m_calcInput.Clear(); m_calcInput.TryAddDecimalPt(); VERIFY_IS_TRUE(m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 1), L"Verify decimal point and leading zero does not count toward maxDigits."); VERIFY_ARE_EQUAL(L"0.1", m_calcInput.ToString(10, false), L"Verify input value checking dec pt and leading zero impact on maxDigits."); } TEST_METHOD(TryAddDigitValues) { // Use an arbitrary value > 16 to test that input accepts digits > hexadecimal 0xF. // TryAddDigit does not validate whether the digit fits within the current radix. for (unsigned int i = 0; i < 25; i++) { VERIFY_IS_TRUE(m_calcInput.TryAddDigit(i, 10, false, L"999", 64, 32), String().Format(L"Verify TryAddDigit succeeds for %d", i)); m_calcInput.Clear(); } } TEST_METHOD(TryAddDigitRolloverBaseCheck) { m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32); VERIFY_IS_FALSE(m_calcInput.TryAddDigit(2, 16, true, L"999", 64, 1), L"Verify TryAddDigit rollover fails for bases other than 8,10."); VERIFY_IS_FALSE(m_calcInput.TryAddDigit(1, 2, true, L"999", 64, 1), L"Verify TryAddDigit rollover fails for bases other than 8,10."); } TEST_METHOD(TryAddDigitRolloverOctalByte) { m_calcInput.TryAddDigit(1, 8, true, L"777", 64, 32); VERIFY_IS_TRUE(m_calcInput.TryAddDigit(2, 8, true, L"377", 8, 1), L"Verify we can add an extra digit in OctalByte if first digit <= 3."); m_calcInput.Clear(); m_calcInput.TryAddDigit(4, 8, true, L"777", 64, 32); VERIFY_IS_FALSE(m_calcInput.TryAddDigit(2, 8, true, L"377", 8, 1), L"Verify we cannot add an extra digit in OctalByte if first digit > 3."); } TEST_METHOD(TryAddDigitRolloverOctalWord) { m_calcInput.TryAddDigit(1, 8, true, L"777", 64, 32); VERIFY_IS_TRUE(m_calcInput.TryAddDigit(2, 8, true, L"377", 16, 1), L"Verify we can add an extra digit in OctalByte if first digit == 1."); m_calcInput.Clear(); m_calcInput.TryAddDigit(2, 8, true, L"777", 64, 32); VERIFY_IS_FALSE(m_calcInput.TryAddDigit(2, 8, true, L"377", 16, 1), L"Verify we cannot add an extra digit in OctalByte if first digit > 1."); } TEST_METHOD(TryAddDigitRolloverOctalDword) { m_calcInput.TryAddDigit(1, 8, true, L"777", 64, 32); VERIFY_IS_TRUE(m_calcInput.TryAddDigit(2, 8, true, L"377", 32, 1), L"Verify we can add an extra digit in OctalByte if first digit <= 3."); m_calcInput.Clear(); m_calcInput.TryAddDigit(4, 8, true, L"777", 64, 32); VERIFY_IS_FALSE(m_calcInput.TryAddDigit(2, 8, true, L"377", 32, 1), L"Verify we cannot add an extra digit in OctalByte if first digit > 3."); } TEST_METHOD(TryAddDigitRolloverOctalQword) { m_calcInput.TryAddDigit(1, 8, true, L"777", 64, 32); VERIFY_IS_TRUE(m_calcInput.TryAddDigit(2, 8, true, L"377", 64, 1), L"Verify we can add an extra digit in OctalByte if first digit == 1."); m_calcInput.Clear(); m_calcInput.TryAddDigit(2, 8, true, L"777", 64, 32); VERIFY_IS_FALSE(m_calcInput.TryAddDigit(2, 8, true, L"377", 64, 1), L"Verify we cannot add an extra digit in OctalByte if first digit > 1."); } TEST_METHOD(TryAddDigitRolloverDecimal) { m_calcInput.TryAddDigit(1, 10, true, L"127", 64, 32); VERIFY_IS_FALSE(m_calcInput.TryAddDigit(0, 10, true, L"1", 8, 1), L"Verify we cannot add a digit if input size matches maxStr size."); m_calcInput.TryAddDigit(2, 10, true, L"127", 64, 32); VERIFY_IS_FALSE(m_calcInput.TryAddDigit(2, 10, true, L"110", 8, 2), L"Verify we cannot add a digit if n char comparison > 0."); VERIFY_IS_TRUE(m_calcInput.TryAddDigit(7, 10, true, L"130", 8, 2), L"Verify we can add a digit if n char comparison < 0."); m_calcInput.Clear(); m_calcInput.TryAddDigit(1, 10, true, L"127", 64, 32); m_calcInput.TryAddDigit(2, 10, true, L"127", 64, 32); VERIFY_IS_FALSE(m_calcInput.TryAddDigit(8, 10, true, L"127", 8, 2), L"Verify we cannot add a digit if digit exceeds max value."); VERIFY_IS_TRUE(m_calcInput.TryAddDigit(7, 10, true, L"127", 8, 2), L"Verify we can add a digit if digit does not exceed max value."); m_calcInput.Backspace(); m_calcInput.TryToggleSign(true, L"127"); VERIFY_IS_FALSE(m_calcInput.TryAddDigit(9, 10, true, L"127", 8, 2), L"Negative value: verify we cannot add a digit if digit exceeds max value."); VERIFY_IS_TRUE(m_calcInput.TryAddDigit(8, 10, true, L"127", 8, 2), L"Negative value: verify we can add a digit if digit does not exceed max value."); } TEST_METHOD(TryAddDecimalPtEmpty) { VERIFY_IS_FALSE(m_calcInput.HasDecimalPt(), L"Verify input has no decimal point."); VERIFY_IS_TRUE(m_calcInput.TryAddDecimalPt(), L"Verify adding decimal to empty input."); VERIFY_IS_TRUE(m_calcInput.HasDecimalPt(), L"Verify input has decimal point."); VERIFY_ARE_EQUAL(L"0.", m_calcInput.ToString(10, false), L"Verify decimal on empty input."); } TEST_METHOD(TryAddDecimalPointTwice) { VERIFY_IS_FALSE(m_calcInput.HasDecimalPt(), L"Verify input has no decimal point."); VERIFY_IS_TRUE(m_calcInput.TryAddDecimalPt(), L"Verify adding decimal to empty input."); VERIFY_IS_TRUE(m_calcInput.HasDecimalPt(), L"Verify input has decimal point."); VERIFY_IS_FALSE(m_calcInput.TryAddDecimalPt(), L"Verify adding decimal point fails if input has decimal point."); } TEST_METHOD(TryAddDecimalPointExponent) { m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32); m_calcInput.TryBeginExponent(); m_calcInput.TryAddDigit(2, 10, false, L"999", 64, 32); VERIFY_IS_FALSE(m_calcInput.TryAddDecimalPt(), L"Verify adding decimal point fails if input has exponent."); } TEST_METHOD(TryBeginExponentNoExponent) { m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32); VERIFY_IS_TRUE(m_calcInput.TryBeginExponent(), L"Verify adding exponent succeeds on input without exponent."); VERIFY_ARE_EQUAL(L"1.e+0", m_calcInput.ToString(10, false), L"Verify exponent present."); } TEST_METHOD(TryBeginExponentWithExponent) { m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32); VERIFY_IS_TRUE(m_calcInput.TryBeginExponent(), L"Verify adding exponent succeeds on input without exponent."); VERIFY_IS_FALSE(m_calcInput.TryBeginExponent(), L"Verify cannot add exponent if input already has exponent."); } TEST_METHOD(BackspaceZero) { m_calcInput.Backspace(); VERIFY_ARE_EQUAL(L"0", m_calcInput.ToString(10, false), L"Verify backspace on 0 is still 0."); } TEST_METHOD(BackspaceSingleChar) { m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32); VERIFY_ARE_EQUAL(L"1", m_calcInput.ToString(10, false), L"Verify input before backspace."); m_calcInput.Backspace(); VERIFY_ARE_EQUAL(L"0", m_calcInput.ToString(10, false), L"Verify input after backspace."); } TEST_METHOD(BackspaceMultiChar) { m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32); m_calcInput.TryAddDigit(2, 10, false, L"999", 64, 32); VERIFY_ARE_EQUAL(L"12", m_calcInput.ToString(10, false), L"Verify input before backspace."); m_calcInput.Backspace(); VERIFY_ARE_EQUAL(L"1", m_calcInput.ToString(10, false), L"Verify input after backspace."); } TEST_METHOD(BackspaceDecimal) { m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32); m_calcInput.TryAddDecimalPt(); VERIFY_ARE_EQUAL(L"1.", m_calcInput.ToString(10, false), L"Verify input before backspace."); VERIFY_IS_TRUE(m_calcInput.HasDecimalPt(), L"Verify input has decimal point."); m_calcInput.Backspace(); VERIFY_ARE_EQUAL(L"1", m_calcInput.ToString(10, false), L"Verify input after backspace."); VERIFY_IS_FALSE(m_calcInput.HasDecimalPt(), L"Verify decimal point was removed."); } TEST_METHOD(BackspaceMultiCharDecimal) { m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32); m_calcInput.TryAddDecimalPt(); m_calcInput.TryAddDigit(2, 10, false, L"999", 64, 32); m_calcInput.TryAddDigit(3, 10, false, L"999", 64, 32); VERIFY_ARE_EQUAL(L"1.23", m_calcInput.ToString(10, false), L"Verify input before backspace."); m_calcInput.Backspace(); VERIFY_ARE_EQUAL(L"1.2", m_calcInput.ToString(10, false), L"Verify input after backspace."); } TEST_METHOD(SetDecimalSymbol) { m_calcInput.TryAddDecimalPt(); VERIFY_ARE_EQUAL(L"0.", m_calcInput.ToString(10, false), L"Verify default decimal point."); m_calcInput.SetDecimalSymbol(L','); VERIFY_ARE_EQUAL(L"0,", m_calcInput.ToString(10, false), L"Verify new decimal point."); } TEST_METHOD(ToStringEmpty) { VERIFY_ARE_EQUAL(L"0", m_calcInput.ToString(10, false), L"Verify ToString of empty value."); } TEST_METHOD(ToStringNegative) { m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32); m_calcInput.TryToggleSign(false, L"999"); VERIFY_ARE_EQUAL(L"-1", m_calcInput.ToString(10, false), L"Verify ToString of negative value."); } TEST_METHOD(ToStringExponentBase10) { m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32); m_calcInput.TryBeginExponent(); VERIFY_ARE_EQUAL(L"1.e+0", m_calcInput.ToString(10, false), L"Verify ToString of empty base10 exponent."); } TEST_METHOD(ToStringExponentBase8) { m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32); m_calcInput.TryBeginExponent(); VERIFY_ARE_EQUAL(L"1.^+0", m_calcInput.ToString(8, false), L"Verify ToString of empty base8 exponent."); } TEST_METHOD(ToStringExponentNegative) { m_calcInput.TryAddDigit(1, 8, false, L"999", 64, 32); m_calcInput.TryBeginExponent(); m_calcInput.TryToggleSign(false, L"999"); VERIFY_ARE_EQUAL(L"1.e-0", m_calcInput.ToString(10, false), L"Verify ToString of empty negative exponent."); } TEST_METHOD(ToStringExponentPositive) { m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32); m_calcInput.TryBeginExponent(); m_calcInput.TryAddDigit(2, 10, false, L"999", 64, 32); m_calcInput.TryAddDigit(3, 10, false, L"999", 64, 32); m_calcInput.TryAddDigit(4, 10, false, L"999", 64, 32); VERIFY_ARE_EQUAL(L"1.e+234", m_calcInput.ToString(10, false), L"Verify ToString of exponent with value."); } TEST_METHOD(ToStringInteger) { m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32); VERIFY_ARE_EQUAL(L"1", m_calcInput.ToString(10, true), L"Verify ToString of integer value hides decimal."); } TEST_METHOD(ToStringBaseTooLong) { wstring maxStr{}; for (size_t i = 0; i < MAX_STRLEN + 1; i++) { maxStr += L"1"; m_calcInput.TryAddDigit(1, 10, false, maxStr, 64, 100); } auto result = m_calcInput.ToString(10, false); VERIFY_IS_TRUE(result.empty(), L"Verify ToString of base value that is too large yields empty string."); } TEST_METHOD(ToStringExponentTooLong) { m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32); m_calcInput.TryBeginExponent(); wstring maxStr{L"11"}; bool exponentCapped = false; for (size_t i = 0; i < MAX_STRLEN + 1; i++) { maxStr += L"1"; if (!m_calcInput.TryAddDigit(1, 10, false, maxStr, 64, MAX_STRLEN + 25)) { exponentCapped = true; } } auto result = m_calcInput.ToString(10, false); // TryAddDigit caps the exponent length to C_EXP_MAX_DIGITS = 4, so ToString() succeeds. // If that cap is removed, ToString() should return an empty string. if (exponentCapped) { VERIFY_ARE_EQUAL(L"1.e+1111", result, L"Verify ToString succeeds; exponent length is capped at C_EXP_MAX_DIGITS."); } else { VERIFY_IS_TRUE(result.empty(), L"Verify ToString of exponent value that is too large yields empty string."); } } TEST_METHOD(ToRational) { m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32); m_calcInput.TryAddDigit(2, 10, false, L"999", 64, 32); m_calcInput.TryAddDigit(3, 10, false, L"999", 64, 32); VERIFY_ARE_EQUAL(L"123", m_calcInput.ToString(10, false), L"Verify input before conversion to rational."); auto rat = m_calcInput.ToRational(10, false); VERIFY_ARE_EQUAL(1, rat.P().Mantissa().size(), L"Verify digit count of rational."); VERIFY_ARE_EQUAL(123, rat.P().Mantissa().front(), L"Verify first digit of mantissa."); } private: CalcEngine::CalcInput m_calcInput; }; }