From b9b0e068cdb03c6d8a3925f47d3742dbc2e7d5c3 Mon Sep 17 00:00:00 2001 From: Rudy Huyn Date: Wed, 13 Nov 2019 15:15:13 -0800 Subject: [PATCH] Convert CopyPasteManager to runtime class (#766) * Convert CopyPasteManager to runtime class * merge AssertUtils and Helpers.h * update onpastemanager --- src/CalcViewModel/CalcViewModel.vcxproj | 1 + .../CalcViewModel.vcxproj.filters | 3 + src/CalcViewModel/Common/CopyPasteManager.cpp | 173 ++--- src/CalcViewModel/Common/CopyPasteManager.h | 131 ++-- src/CalcViewModel/Common/NumberBase.h | 16 + src/CalcViewModel/Common/Utils.cpp | 4 +- src/CalcViewModel/Common/Utils.h | 2 +- .../StandardCalculatorViewModel.cpp | 17 +- .../StandardCalculatorViewModel.h | 3 +- src/CalcViewModel/UnitConverterViewModel.cpp | 2 +- src/CalcViewModel/pch.h | 2 + src/Calculator/Views/UnitConverter.xaml.cpp | 2 +- .../CopyPasteManagerTest.cpp | 591 +++++++++++------- src/CalculatorUnitTests/Helpers.h | 15 +- .../StandardViewModelUnitTests.cpp | 2 + 15 files changed, 604 insertions(+), 360 deletions(-) create mode 100644 src/CalcViewModel/Common/NumberBase.h diff --git a/src/CalcViewModel/CalcViewModel.vcxproj b/src/CalcViewModel/CalcViewModel.vcxproj index 8eaefc4..49bc036 100644 --- a/src/CalcViewModel/CalcViewModel.vcxproj +++ b/src/CalcViewModel/CalcViewModel.vcxproj @@ -337,6 +337,7 @@ + diff --git a/src/CalcViewModel/CalcViewModel.vcxproj.filters b/src/CalcViewModel/CalcViewModel.vcxproj.filters index 91b5b8b..ac5d41d 100644 --- a/src/CalcViewModel/CalcViewModel.vcxproj.filters +++ b/src/CalcViewModel/CalcViewModel.vcxproj.filters @@ -196,6 +196,9 @@ Common + + Common + diff --git a/src/CalcViewModel/Common/CopyPasteManager.cpp b/src/CalcViewModel/Common/CopyPasteManager.cpp index e4df0da..815f3a8 100644 --- a/src/CalcViewModel/Common/CopyPasteManager.cpp +++ b/src/CalcViewModel/Common/CopyPasteManager.cpp @@ -11,9 +11,11 @@ using namespace concurrency; using namespace CalculatorApp; using namespace CalculatorApp::Common; using namespace Platform; +using namespace Platform::Collections; using namespace Windows::Foundation; using namespace Windows::System; using namespace Windows::ApplicationModel::DataTransfer; +using namespace Windows::Foundation::Collections; StringReference PasteErrorString(L"NoOp"); @@ -58,6 +60,7 @@ static const array, 4> programmerModePatterns = { wregex(c_wspcLParens + c_binProgrammerChars + L"[bB]?" + c_wspcRParens) } } }; static const array unitConverterPatterns = { wregex(c_wspc + c_signedDecFloat + c_wspc) }; + void CopyPasteManager::CopyToClipboard(String ^ stringToCopy) { // Copy the string to the clipboard @@ -66,7 +69,7 @@ void CopyPasteManager::CopyToClipboard(String ^ stringToCopy) Clipboard::SetContent(dataPackage); } -IAsyncOperation ^ CopyPasteManager::GetStringToPaste(ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, BitLength bitLengthType) +IAsyncOperation ^ CopyPasteManager::GetStringToPaste(ViewMode mode, CategoryGroupType modeType, NumberBase programmerNumberBase, BitLength bitLengthType) { // Retrieve the text in the clipboard auto dataPackageView = Clipboard::GetContent(); @@ -91,7 +94,7 @@ bool CopyPasteManager::HasStringToPaste() return Clipboard::GetContent()->Contains(StandardDataFormats::Text); } -String ^ CopyPasteManager::ValidatePasteExpression(String ^ pastedText, ViewMode mode, int programmerNumberBase, BitLength bitLengthType) +String ^ CopyPasteManager::ValidatePasteExpression(String ^ pastedText, ViewMode mode, NumberBase programmerNumberBase, BitLength bitLengthType) { return ValidatePasteExpression(pastedText, mode, NavCategory::GetGroupType(mode), programmerNumberBase, bitLengthType); } @@ -102,7 +105,7 @@ String String ^ pastedText, ViewMode mode, CategoryGroupType modeType, - int programmerNumberBase, + NumberBase programmerNumberBase, BitLength bitLengthType) { if (pastedText->Length() > MaxPasteableLength) @@ -116,7 +119,7 @@ String String ^ englishString = LocalizationSettings::GetInstance().GetEnglishValueFromLocalizedDigits(pastedText); // Removing the spaces, comma separator from the pasteExpression to allow pasting of expressions like 1 + 2+1,333 - wstring pasteExpression = RemoveUnwantedCharsFromWstring(englishString->Data()); + auto pasteExpression = wstring(RemoveUnwantedCharsFromString(englishString)->Data()); // If the last character is an = sign, remove it from the pasteExpression to allow evaluating the result on paste. if (!pasteExpression.empty() && pasteExpression.back() == L'=') @@ -126,8 +129,8 @@ String // Extract operands from the expression to make regex comparison easy and quick. For whole expression it was taking too much of time. // Operands vector will have the list of operands in the pasteExpression - vector operands = ExtractOperands(pasteExpression, mode); - if (operands.empty()) + auto operands = ExtractOperands(StringReference(pasteExpression.c_str()), mode); + if (operands->Size == 0) { // return NoOp to indicate don't paste anything. return PasteErrorString; @@ -135,7 +138,8 @@ String if (modeType == CategoryGroupType::Converter) { - operands = { pasteExpression }; + operands->Clear(); + operands->Append(ref new String(pasteExpression.c_str())); } // validate each operand with patterns for different modes @@ -148,9 +152,9 @@ String return pastedText; } -vector CopyPasteManager::ExtractOperands(const wstring& pasteExpression, ViewMode mode) +IVector ^ CopyPasteManager::ExtractOperands(Platform::String ^ pasteExpression, ViewMode mode) { - vector operands{}; + auto operands = ref new Vector(); size_t lastIndex = 0; bool haveOperator = false; bool startExpCounting = false; @@ -176,19 +180,20 @@ vector CopyPasteManager::ExtractOperands(const wstring& pasteExpression // This will have the exponent length size_t expLength = 0; - for (size_t i = 0; i < pasteExpression.length(); i++) + int i = -1; + for (auto currentChar : pasteExpression) { - wchar_t currentChar = pasteExpression.at(i); + ++i; // if the current character is not a valid one don't process it if (validCharacterSet.find(currentChar) == wstring_view::npos) { continue; } - if (operands.size() >= MaxOperandCount) + if (operands->Size >= MaxOperandCount) { TraceLogger::GetInstance()->LogError(mode, L"CopyPasteManager::ExtractOperands", L"OperandCountGreaterThanMaxCount"); - operands.clear(); + operands->Clear(); return operands; } @@ -202,7 +207,7 @@ vector CopyPasteManager::ExtractOperands(const wstring& pasteExpression if (expLength > MaxExponentLength) { TraceLogger::GetInstance()->LogError(mode, L"CopyPasteManager::ExtractOperands", L"ExponentLengthGreaterThanMaxLength"); - operands.clear(); + operands->Clear(); return operands; } } @@ -222,7 +227,7 @@ vector CopyPasteManager::ExtractOperands(const wstring& pasteExpression { // don't break the expression into operands if the encountered character corresponds to sign command(+-) if (isPreviousOpenParen || startOfExpression || isPreviousOperator - || ((mode != ViewMode::Programmer) && !((i != 0) && (pasteExpression.at(i - 1) != L'e')))) + || ((mode != ViewMode::Programmer) && !((i != 0) && pasteExpression->Data()[i - 1] != L'e'))) { isPreviousOperator = false; continue; @@ -233,7 +238,7 @@ vector CopyPasteManager::ExtractOperands(const wstring& pasteExpression expLength = 0; haveOperator = true; isPreviousOperator = true; - operands.push_back(pasteExpression.substr(lastIndex, i - lastIndex)); + operands->Append(ref new String(wstring(pasteExpression->Data()).substr(lastIndex, i - lastIndex).c_str())); lastIndex = i + 1; } else @@ -241,31 +246,31 @@ vector CopyPasteManager::ExtractOperands(const wstring& pasteExpression isPreviousOperator = false; } - isPreviousOpenParen = (pasteExpression.at(i) == L'('); + isPreviousOpenParen = (currentChar == L'('); startOfExpression = false; } if (!haveOperator) { - operands.clear(); - operands.push_back(pasteExpression); + operands->Clear(); + operands->Append(pasteExpression); } else { - operands.push_back(pasteExpression.substr(lastIndex, pasteExpression.length() - 1)); + operands->Append(ref new String(wstring(pasteExpression->Data()).substr(lastIndex, pasteExpression->Length() - 1).c_str())); } return operands; } bool CopyPasteManager::ExpressionRegExMatch( - vector operands, + IVector ^ operands, ViewMode mode, CategoryGroupType modeType, - int programmerNumberBase, + NumberBase programmerNumberBase, BitLength bitLengthType) { - if (operands.empty()) + if (operands->Size == 0) { return false; } @@ -282,14 +287,16 @@ bool CopyPasteManager::ExpressionRegExMatch( } else if (mode == ViewMode::Programmer) { - patterns.assign(programmerModePatterns[programmerNumberBase - HexBase].begin(), programmerModePatterns[programmerNumberBase - HexBase].end()); + patterns.assign( + programmerModePatterns[(int)programmerNumberBase - (int)NumberBase::HexBase].begin(), + programmerModePatterns[(int)programmerNumberBase - (int)NumberBase::HexBase].end()); } else if (modeType == CategoryGroupType::Converter) { patterns.assign(unitConverterPatterns.begin(), unitConverterPatterns.end()); } - const auto [maxOperandLength, maxOperandValue] = GetMaxOperandLengthAndValue(mode, modeType, programmerNumberBase, bitLengthType); + auto maxOperandLengthAndValue = GetMaxOperandLengthAndValue(mode, modeType, programmerNumberBase, bitLengthType); bool expMatched = true; for (const auto& operand : operands) @@ -298,34 +305,34 @@ bool CopyPasteManager::ExpressionRegExMatch( bool operandMatched = false; for (const auto& pattern : patterns) { - operandMatched = operandMatched || regex_match(operand, pattern); + operandMatched = operandMatched || regex_match(operand->Data(), pattern); } if (operandMatched) { // Remove characters that are valid in the expression but we do not want to include in length calculations // or which will break conversion from string-to-ULL. - const wstring operandValue = SanitizeOperand(operand); + auto operandValue = SanitizeOperand(operand); // If an operand exceeds the maximum length allowed, break and return. - if (OperandLength(operandValue, mode, modeType, programmerNumberBase) > maxOperandLength) + if (OperandLength(operandValue, mode, modeType, programmerNumberBase) > maxOperandLengthAndValue.maxLength) { expMatched = false; break; } // If maxOperandValue is set and the operandValue exceeds it, break and return. - if (maxOperandValue != 0) + if (maxOperandLengthAndValue.maxValue != 0) { - unsigned long long int operandAsULL = 0; - if (!TryOperandToULL(operandValue, programmerNumberBase, operandAsULL)) + auto operandAsULL = TryOperandToULL(operandValue, programmerNumberBase); + if (operandAsULL == nullptr) { // Operand was empty, received invalid_argument, or received out_of_range. Input is invalid. expMatched = false; break; } - if (operandAsULL > maxOperandValue) + if (operandAsULL->Value > maxOperandLengthAndValue.maxValue) { expMatched = false; break; @@ -339,19 +346,23 @@ bool CopyPasteManager::ExpressionRegExMatch( return expMatched; } -pair -CopyPasteManager::GetMaxOperandLengthAndValue(ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, BitLength bitLengthType) +CopyPasteMaxOperandLengthAndValue +CopyPasteManager::GetMaxOperandLengthAndValue(ViewMode mode, CategoryGroupType modeType, NumberBase programmerNumberBase, BitLength bitLengthType) { constexpr size_t defaultMaxOperandLength = 0; constexpr uint64_t defaultMaxValue = 0; - + CopyPasteMaxOperandLengthAndValue res; if (mode == ViewMode::Standard) { - return make_pair(MaxStandardOperandLength, defaultMaxValue); + res.maxLength = MaxStandardOperandLength; + res.maxValue = defaultMaxValue; + return res; } else if (mode == ViewMode::Scientific) { - return make_pair(MaxScientificOperandLength, defaultMaxValue); + res.maxLength = MaxScientificOperandLength; + res.maxValue = defaultMaxValue; + return res; } else if (mode == ViewMode::Programmer) { @@ -375,65 +386,69 @@ CopyPasteManager::GetMaxOperandLengthAndValue(ViewMode mode, CategoryGroupType m double bitsPerDigit = 0; switch (programmerNumberBase) { - case BinBase: + case NumberBase::BinBase: bitsPerDigit = log2(2); break; - case OctBase: + case NumberBase::OctBase: bitsPerDigit = log2(8); break; - case DecBase: + case NumberBase::DecBase: bitsPerDigit = log2(10); break; - case HexBase: + case NumberBase::HexBase: bitsPerDigit = log2(16); break; } - unsigned int signBit = (programmerNumberBase == DecBase) ? 1 : 0; + unsigned int signBit = (programmerNumberBase == NumberBase::DecBase) ? 1 : 0; - const auto maxLength = static_cast(ceil((bitLength - signBit) / bitsPerDigit)); + const auto maxLength = static_cast(ceil((bitLength - signBit) / bitsPerDigit)); const uint64_t maxValue = UINT64_MAX >> (MaxProgrammerBitLength - (bitLength - signBit)); - return make_pair(maxLength, maxValue); + res.maxLength = maxLength; + res.maxValue = maxValue; + return res; } else if (modeType == CategoryGroupType::Converter) { - return make_pair(MaxConverterInputLength, defaultMaxValue); + res.maxLength = MaxConverterInputLength; + res.maxValue = defaultMaxValue; + return res; } - return make_pair(defaultMaxOperandLength, defaultMaxValue); + res.maxLength = defaultMaxOperandLength; + res.maxValue = defaultMaxValue; + return res; } -wstring CopyPasteManager::SanitizeOperand(const wstring& operand) +Platform::String ^ CopyPasteManager::SanitizeOperand(Platform::String ^ operand) { wchar_t unWantedChars[] = { L'\'', L'_', L'`', L'(', L')', L'-', L'+' }; - return Utils::RemoveUnwantedCharsFromWstring(operand, unWantedChars, static_cast(size(unWantedChars))); + return ref new String(Utils::RemoveUnwantedCharsFromString(operand->Data(), unWantedChars, static_cast(size(unWantedChars))).c_str()); } -bool CopyPasteManager::TryOperandToULL(const wstring& operand, int numberBase, unsigned long long int& result) +IBox ^ CopyPasteManager::TryOperandToULL(String ^ operand, NumberBase numberBase) { - result = 0; - - if (operand.length() == 0 || operand.front() == L'-') + if (operand->Length() == 0 || operand->Data()[0] == L'-') { - return false; + return nullptr; } int intBase; switch (numberBase) { - case HexBase: + case NumberBase::HexBase: intBase = 16; break; - case OctBase: + case NumberBase::OctBase: intBase = 8; break; - case BinBase: + case NumberBase::BinBase: intBase = 2; break; default: - case DecBase: + case NumberBase::DecBase: intBase = 10; break; } @@ -441,8 +456,7 @@ bool CopyPasteManager::TryOperandToULL(const wstring& operand, int numberBase, u wstring::size_type size = 0; try { - result = stoull(operand, &size, intBase); - return true; + return stoull(operand->Data(), &size, intBase); } catch (const invalid_argument&) { @@ -453,14 +467,14 @@ bool CopyPasteManager::TryOperandToULL(const wstring& operand, int numberBase, u // Do nothing } - return false; + return nullptr; } -size_t CopyPasteManager::OperandLength(const wstring& operand, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase) +ULONG32 CopyPasteManager::OperandLength(Platform::String ^ operand, ViewMode mode, CategoryGroupType modeType, NumberBase programmerNumberBase) { if (modeType == CategoryGroupType::Converter) { - return operand.length(); + return operand->Length(); } switch (mode) @@ -477,45 +491,46 @@ size_t CopyPasteManager::OperandLength(const wstring& operand, ViewMode mode, Ca } } -size_t CopyPasteManager::StandardScientificOperandLength(const wstring& operand) +ULONG32 CopyPasteManager::StandardScientificOperandLength(Platform::String ^ operand) { - const bool hasDecimal = operand.find('.') != wstring::npos; + auto operandWstring = wstring(operand->Data()); + const bool hasDecimal = operandWstring.find('.') != wstring::npos; if (hasDecimal) { - if (operand.length() >= 2) + if (operandWstring.length() >= 2) { - if ((operand[0] == L'0') && (operand[1] == L'.')) + if ((operandWstring[0] == L'0') && (operandWstring[1] == L'.')) { - return operand.length() - 2; + return static_cast(operandWstring.length() - 2); } else { - return operand.length() - 1; + return static_cast(operandWstring.length() - 1); } } } - return operand.length(); + return static_cast(operandWstring.length()); } -size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int numberBase) +ULONG32 CopyPasteManager::ProgrammerOperandLength(Platform::String ^ operand, NumberBase numberBase) { vector prefixes{}; vector suffixes{}; switch (numberBase) { - case BinBase: + case NumberBase::BinBase: prefixes = { L"0B", L"0Y" }; suffixes = { L"B" }; break; - case DecBase: + case NumberBase::DecBase: prefixes = { L"-", L"0N" }; break; - case OctBase: + case NumberBase::OctBase: prefixes = { L"0T", L"0O" }; break; - case HexBase: + case NumberBase::HexBase: prefixes = { L"0X" }; suffixes = { L"H" }; break; @@ -528,10 +543,10 @@ size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int num const array uintSuffixes = { L"ULL", L"UL", L"LL", L"U", L"L" }; suffixes.insert(suffixes.end(), uintSuffixes.begin(), uintSuffixes.end()); - wstring operandUpper = operand; + wstring operandUpper = wstring(operand->Data()); transform(operandUpper.begin(), operandUpper.end(), operandUpper.begin(), towupper); - size_t len = operand.length(); + size_t len = operand->Length(); // Detect if there is a suffix and subtract its length // Check suffixes first to allow e.g. "0b" to result in length 1 (value 0), rather than length 0 (no value). @@ -564,7 +579,7 @@ size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int num } } - return len; + return static_cast(len); } // return wstring after removing characters like space, comma, double quotes, and monetary prefix currency symbols supported by the Windows keyboard: @@ -579,10 +594,10 @@ size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int num // Indian rupee(₹) - 8377 // pound(£) - 163 // euro(€) - 8364 -wstring CopyPasteManager::RemoveUnwantedCharsFromWstring(const wstring& input) +Platform::String ^ CopyPasteManager::RemoveUnwantedCharsFromString(Platform::String ^ input) { wchar_t unWantedChars[] = { L' ', L',', L'"', 165, 164, 8373, 36, 8353, 8361, 8362, 8358, 8377, 163, 8364, 8234, 8235, 8236, 8237 }; - return Utils::RemoveUnwantedCharsFromWstring(input, unWantedChars, 18); + return ref new String(Utils::RemoveUnwantedCharsFromString(input->Data(), unWantedChars, 18).c_str()); } bool CopyPasteManager::IsErrorMessage(Platform::String ^ message) diff --git a/src/CalcViewModel/Common/CopyPasteManager.h b/src/CalcViewModel/Common/CopyPasteManager.h index 1b2f0bb..b8850d4 100644 --- a/src/CalcViewModel/Common/CopyPasteManager.h +++ b/src/CalcViewModel/Common/CopyPasteManager.h @@ -6,6 +6,7 @@ #include "AppResourceProvider.h" #include "NavCategory.h" #include "BitLength.h" +#include "NumberBase.h" namespace CalculatorUnitTests { @@ -14,71 +15,119 @@ namespace CalculatorUnitTests namespace CalculatorApp { - inline constexpr auto HexBase = 5; - inline constexpr auto DecBase = 6; - inline constexpr auto OctBase = 7; - inline constexpr auto BinBase = 8; +public + value struct CopyPasteMaxOperandLengthAndValue + { + unsigned int maxLength; + unsigned long long maxValue; + }; public ref class CopyPasteManager sealed { public: static void CopyToClipboard(Platform::String ^ stringToCopy); - static Windows::Foundation::IAsyncOperation^ GetStringToPaste( - CalculatorApp::Common::ViewMode mode, - CalculatorApp::Common::CategoryGroupType modeType, - int programmerNumberBase, - CalculatorApp::Common::BitLength bitLengthType); + static Windows::Foundation::IAsyncOperation< + Platform::String + ^> ^ GetStringToPaste(CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, CalculatorApp::Common::NumberBase programmerNumberBase, CalculatorApp::Common::BitLength bitLengthType); static bool HasStringToPaste(); static bool IsErrorMessage(Platform::String ^ message); + static property unsigned int MaxPasteableLength + { + unsigned int get() + { + return MaxPasteableLengthValue; + } + } + static property unsigned int MaxOperandCount + { + unsigned int get() + { + return MaxOperandCountValue; + } + } + static property unsigned int MaxStandardOperandLength + { + unsigned int get() + { + return MaxStandardOperandLengthValue; + } + } + static property unsigned int MaxScientificOperandLength + { + unsigned int get() + { + return MaxScientificOperandLengthValue; + } + } + + static property unsigned int MaxConverterInputLength + { + unsigned int get() + { + return MaxConverterInputLengthValue; + } + } + + static property unsigned int MaxExponentLength + { + unsigned int get() + { + return MaxExponentLengthValue; + } + } + + static property unsigned int MaxProgrammerBitLength + { + unsigned int get() + { + return MaxProgrammerBitLengthValue; + } + } - private: static Platform::String ^ ValidatePasteExpression( Platform::String ^ pastedText, CalculatorApp::Common::ViewMode mode, - int programmerNumberBase, + CalculatorApp::Common::NumberBase programmerNumberBase, CalculatorApp::Common::BitLength bitLengthType); static Platform::String ^ ValidatePasteExpression( Platform::String ^ pastedText, CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, - int programmerNumberBase, + CalculatorApp::Common::NumberBase programmerNumberBase, CalculatorApp::Common::BitLength bitLengthType); - - static std::vector - ExtractOperands(const std::wstring& pasteExpression, CalculatorApp::Common::ViewMode mode); + static CopyPasteMaxOperandLengthAndValue GetMaxOperandLengthAndValue( + CalculatorApp::Common::ViewMode mode, + CalculatorApp::Common::CategoryGroupType modeType, + CalculatorApp::Common::NumberBase programmerNumberBase, + CalculatorApp::Common::BitLength bitLengthType); + static Windows::Foundation::Collections::IVector< + Platform::String ^> ^ ExtractOperands(Platform::String ^ pasteExpression, CalculatorApp::Common::ViewMode mode); static bool ExpressionRegExMatch( - std::vector operands, + Windows::Foundation::Collections::IVector ^ operands, CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, - int programmerNumberBase = -1, - CalculatorApp::Common::BitLength bitLengthType = CalculatorApp::Common::BitLength::BitLengthUnknown); - - static std::pair GetMaxOperandLengthAndValue( + CalculatorApp::Common::NumberBase programmerNumberBase, + CalculatorApp::Common::BitLength bitLengthType); + static Platform::String ^ SanitizeOperand(Platform::String ^ operand); + static Platform::String ^ RemoveUnwantedCharsFromString(Platform::String ^ input); + static Platform::IBox ^ TryOperandToULL(Platform::String ^ operand, CalculatorApp::Common::NumberBase numberBase); + static ULONG32 StandardScientificOperandLength(Platform::String ^ operand); + static ULONG32 OperandLength( + Platform::String ^ operand, CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, - int programmerNumberBase = -1, - CalculatorApp::Common::BitLength bitLengthType = CalculatorApp::Common::BitLength::BitLengthUnknown); - static std::wstring SanitizeOperand(const std::wstring& operand); - static bool TryOperandToULL(const std::wstring& operand, int numberBase, unsigned long long int& result); - static size_t OperandLength( - const std::wstring& operand, - CalculatorApp::Common::ViewMode mode, - CalculatorApp::Common::CategoryGroupType modeType, - int programmerNumberBase = -1); - static size_t StandardScientificOperandLength(const std::wstring& operand); - static size_t ProgrammerOperandLength(const std::wstring& operand, int numberBase); - static std::wstring RemoveUnwantedCharsFromWstring(const std::wstring& input); + CalculatorApp::Common::NumberBase programmerNumberBase); + static ULONG32 ProgrammerOperandLength(Platform::String ^ operand, CalculatorApp::Common::NumberBase numberBase); - static constexpr size_t MaxStandardOperandLength = 16; - static constexpr size_t MaxScientificOperandLength = 32; - static constexpr size_t MaxConverterInputLength = 16; - static constexpr size_t MaxOperandCount = 100; - static constexpr size_t MaxPasteableLength = 512; - static constexpr size_t MaxExponentLength = 4; - static constexpr size_t MaxProgrammerBitLength = 64; - - friend class CalculatorUnitTests::CopyPasteManagerTest; + private: + static constexpr size_t MaxStandardOperandLengthValue = 16; + static constexpr size_t MaxScientificOperandLengthValue = 32; + static constexpr size_t MaxConverterInputLengthValue = 16; + static constexpr size_t MaxOperandCountValue = 100; + static constexpr size_t MaxExponentLengthValue = 4; + static constexpr size_t MaxProgrammerBitLengthValue = 64; + static constexpr size_t MaxPasteableLengthValue = 512; }; } diff --git a/src/CalcViewModel/Common/NumberBase.h b/src/CalcViewModel/Common/NumberBase.h new file mode 100644 index 0000000..4e15efa --- /dev/null +++ b/src/CalcViewModel/Common/NumberBase.h @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once +namespace CalculatorApp::Common +{ +public + enum class NumberBase + { + Unknown = -1, + HexBase = 5, + DecBase = 6, + OctBase = 7, + BinBase = 8 + }; +}; diff --git a/src/CalcViewModel/Common/Utils.cpp b/src/CalcViewModel/Common/Utils.cpp index c0e1f5a..0fc2e66 100644 --- a/src/CalcViewModel/Common/Utils.cpp +++ b/src/CalcViewModel/Common/Utils.cpp @@ -48,7 +48,7 @@ String ^ Utils::GetStringValue(String ^ input) double Utils::GetDoubleFromWstring(wstring input) { wchar_t unWantedChars[] = { L' ', L',', 8234, 8235, 8236, 8237 }; - wstring ws = RemoveUnwantedCharsFromWstring(input, unWantedChars, 6); + wstring ws = RemoveUnwantedCharsFromString(input, unWantedChars, 6); return stod(ws); } @@ -81,7 +81,7 @@ bool Utils::IsLastCharacterTarget(_In_ wstring const& input, _In_ wchar_t target } // Return wstring after removing characters specified by unwantedChars array -wstring Utils::RemoveUnwantedCharsFromWstring(wstring input, wchar_t* unwantedChars, unsigned int size) +wstring Utils::RemoveUnwantedCharsFromString(wstring input, wchar_t* unwantedChars, unsigned int size) { for (unsigned int i = 0; i < size; ++i) { diff --git a/src/CalcViewModel/Common/Utils.h b/src/CalcViewModel/Common/Utils.h index e0638bf..84ce20d 100644 --- a/src/CalcViewModel/Common/Utils.h +++ b/src/CalcViewModel/Common/Utils.h @@ -379,7 +379,7 @@ namespace Utils void IFTPlatformException(HRESULT hr); Platform::String ^ GetStringValue(Platform::String ^ input); bool IsLastCharacterTarget(std::wstring const& input, wchar_t target); - std::wstring RemoveUnwantedCharsFromWstring(std::wstring inputString, wchar_t* unwantedChars, unsigned int size); + std::wstring RemoveUnwantedCharsFromString(std::wstring inputString, wchar_t* unwantedChars, unsigned int size); double GetDoubleFromWstring(std::wstring input); int GetWindowId(); void RunOnUIThreadNonblocking(std::function&& function, _In_ Windows::UI::Core::CoreDispatcher ^ currentDispatcher); diff --git a/src/CalcViewModel/StandardCalculatorViewModel.cpp b/src/CalcViewModel/StandardCalculatorViewModel.cpp index cce5c38..6eb23d2 100644 --- a/src/CalcViewModel/StandardCalculatorViewModel.cpp +++ b/src/CalcViewModel/StandardCalculatorViewModel.cpp @@ -14,6 +14,7 @@ using namespace CalculatorApp::Common; using namespace CalculatorApp::Common::Automation; using namespace CalculatorApp::ViewModel; using namespace CalculationManager; +using namespace concurrency; using namespace Platform; using namespace Platform::Collections; using namespace std; @@ -680,23 +681,23 @@ void StandardCalculatorViewModel::OnButtonPressed(Object ^ parameter) } } -int StandardCalculatorViewModel::GetNumberBase() +NumberBase StandardCalculatorViewModel::GetNumberBase() { if (CurrentRadixType == HEX_RADIX) { - return HexBase; + return NumberBase::HexBase; } else if (CurrentRadixType == DEC_RADIX) { - return DecBase; + return NumberBase::DecBase; } else if (CurrentRadixType == OCT_RADIX) { - return OctBase; + return NumberBase::OctBase; } else { - return BinBase; + return NumberBase::BinBase; } } @@ -712,7 +713,7 @@ void StandardCalculatorViewModel::OnPasteCommand(Object ^ parameter) { auto that(this); ViewMode mode; - int NumberBase = -1; + NumberBase numberBase = NumberBase::Unknown; BitLength bitLengthType = BitLength::BitLengthUnknown; if (IsScientific) { @@ -721,7 +722,7 @@ void StandardCalculatorViewModel::OnPasteCommand(Object ^ parameter) else if (IsProgrammer) { mode = ViewMode::Programmer; - NumberBase = GetNumberBase(); + numberBase = GetNumberBase(); bitLengthType = m_valueBitLength; } else @@ -735,7 +736,7 @@ void StandardCalculatorViewModel::OnPasteCommand(Object ^ parameter) } // Ensure that the paste happens on the UI thread - create_task(CopyPasteManager::GetStringToPaste(mode, NavCategory::GetGroupType(mode), NumberBase, bitLengthType)) + create_task(CopyPasteManager::GetStringToPaste(mode, NavCategory::GetGroupType(mode), numberBase, bitLengthType)) .then([that, mode](String ^ pastedString) { that->OnPaste(pastedString); }, concurrency::task_continuation_context::use_current()); } diff --git a/src/CalcViewModel/StandardCalculatorViewModel.h b/src/CalcViewModel/StandardCalculatorViewModel.h index 31f0f7f..a58ffa1 100644 --- a/src/CalcViewModel/StandardCalculatorViewModel.h +++ b/src/CalcViewModel/StandardCalculatorViewModel.h @@ -10,6 +10,7 @@ #include "HistoryViewModel.h" #include "MemoryItemViewModel.h" #include "Common/BitLength.h" +#include "Common/NumberBase.h" namespace CalculatorFunctionalTests { @@ -39,7 +40,7 @@ namespace CalculatorApp StandardCalculatorViewModel(); void UpdateOperand(int pos, Platform::String ^ text); void UpdatecommandsInRecordingMode(); - int GetNumberBase(); + CalculatorApp::Common::NumberBase GetNumberBase(); OBSERVABLE_OBJECT_CALLBACK(OnPropertyChanged); OBSERVABLE_PROPERTY_RW(Platform::String ^, DisplayValue); diff --git a/src/CalcViewModel/UnitConverterViewModel.cpp b/src/CalcViewModel/UnitConverterViewModel.cpp index 8685c0d..bab3c78 100644 --- a/src/CalcViewModel/UnitConverterViewModel.cpp +++ b/src/CalcViewModel/UnitConverterViewModel.cpp @@ -517,7 +517,7 @@ void UnitConverterViewModel::OnPasteCommand(Platform::Object ^ parameter) // Any converter ViewMode is fine here. auto that(this); - create_task(CopyPasteManager::GetStringToPaste(m_Mode, NavCategory::GetGroupType(m_Mode), -1, BitLength::BitLengthUnknown)) + create_task(CopyPasteManager::GetStringToPaste(m_Mode, NavCategory::GetGroupType(m_Mode), NumberBase::Unknown, BitLength::BitLengthUnknown)) .then([that](String ^ pastedString) { that->OnPaste(pastedString); }, concurrency::task_continuation_context::use_current()); } diff --git a/src/CalcViewModel/pch.h b/src/CalcViewModel/pch.h index 575a1f0..77e1094 100644 --- a/src/CalcViewModel/pch.h +++ b/src/CalcViewModel/pch.h @@ -31,6 +31,8 @@ #include #include #include +#include + // C++\WinRT Headers #include "winrt/base.h" #include "winrt/Windows.Foundation.Diagnostics.h" diff --git a/src/Calculator/Views/UnitConverter.xaml.cpp b/src/Calculator/Views/UnitConverter.xaml.cpp index dbfd1e6..f74d0a5 100644 --- a/src/Calculator/Views/UnitConverter.xaml.cpp +++ b/src/Calculator/Views/UnitConverter.xaml.cpp @@ -244,7 +244,7 @@ void UnitConverter::OnCopyMenuItemClicked(_In_ Object ^ sender, _In_ RoutedEvent void UnitConverter::OnPasteMenuItemClicked(_In_ Object ^ sender, _In_ RoutedEventArgs ^ e) { auto that(this); - create_task(CopyPasteManager::GetStringToPaste(Model->Mode, CategoryGroupType::Converter, -1, BitLength::BitLengthUnknown)) + create_task(CopyPasteManager::GetStringToPaste(Model->Mode, CategoryGroupType::Converter, NumberBase::Unknown, BitLength::BitLengthUnknown)) .then([that](String ^ pastedString) { that->Model->OnPaste(pastedString); }); } diff --git a/src/CalculatorUnitTests/CopyPasteManagerTest.cpp b/src/CalculatorUnitTests/CopyPasteManagerTest.cpp index a5e0425..ee9eb1d 100644 --- a/src/CalculatorUnitTests/CopyPasteManagerTest.cpp +++ b/src/CalculatorUnitTests/CopyPasteManagerTest.cpp @@ -6,12 +6,14 @@ #include "CalcViewModel/StandardCalculatorViewModel.h" #include "CalcViewModel/Common/CopyPasteManager.h" +#include "Helpers.h" using namespace CalculationManager; using namespace CalculatorApp; using namespace CalculatorApp::Common; using namespace CalculatorApp::ViewModel; using namespace Platform; +using namespace Platform::Collections; using namespace std; using namespace Windows::ApplicationModel::DataTransfer; using namespace Windows::ApplicationModel::Resources; @@ -39,6 +41,13 @@ namespace CalculatorUnitTests } \ } +#define VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS(ref, length, value, ...) \ + { \ + auto result = ref; \ + Assert::IsTrue(ref.maxLength == length, __VA_ARGS__); \ + Assert::IsTrue(ref.maxValue == value, __VA_ARGS__); \ + } + TEST_CLASS(CopyPasteManagerTest) { public: @@ -58,36 +67,45 @@ namespace CalculatorUnitTests TEST_METHOD(ValidatePasteExpressionErrorStates) { wstring exp_TooLong = L""; - for (int i = 0; i < m_CopyPasteManager->MaxPasteableLength / 8; i++) + for (unsigned int i = 0; i < CopyPasteManager::MaxPasteableLength / 8; i++) { exp_TooLong += L"-1234567"; } VERIFY_ARE_EQUAL( m_CopyPasteManager->ValidatePasteExpression( - StringReference(exp_TooLong.c_str()), ViewMode::Standard, CategoryGroupType::Calculator, -1, BitLength::BitLengthUnknown), + StringReference(exp_TooLong.c_str()), + ViewMode::Standard, + CategoryGroupType::Calculator, + NumberBase::Unknown, + BitLength::BitLengthUnknown), StringReference(exp_TooLong.c_str()), L"Verify ValidatePasteExpression handles expressions up to max length"); - exp_TooLong += L'1'; + exp_TooLong += L"1"; VERIFY_ARE_EQUAL( m_CopyPasteManager->ValidatePasteExpression( - StringReference(exp_TooLong.c_str()), ViewMode::Standard, CategoryGroupType::Calculator, -1, BitLength::BitLengthUnknown), + StringReference(exp_TooLong.c_str()), + ViewMode::Standard, + CategoryGroupType::Calculator, + NumberBase::Unknown, + BitLength::BitLengthUnknown), StringReference(L"NoOp"), L"Verify ValidatePasteExpression returns NoOp for strings over max length"); VERIFY_ARE_EQUAL( m_CopyPasteManager->ValidatePasteExpression( - StringReference(L""), ViewMode::Standard, CategoryGroupType::Calculator, -1, BitLength::BitLengthUnknown), + StringReference(L""), ViewMode::Standard, CategoryGroupType::Calculator, NumberBase::Unknown, BitLength::BitLengthUnknown), StringReference(L"NoOp"), L"Verify empty string is invalid"); VERIFY_ARE_EQUAL( m_CopyPasteManager->ValidatePasteExpression( - StringReference(L"1a23f456"), ViewMode::Standard, CategoryGroupType::Calculator, -1, BitLength::BitLengthUnknown), + StringReference(L"1a23f456"), ViewMode::Standard, CategoryGroupType::Calculator, NumberBase::Unknown, BitLength::BitLengthUnknown), StringReference(L"NoOp"), L"Verify pasting unsupported strings for the current mode is invalid"); VERIFY_ARE_EQUAL( - m_CopyPasteManager->ValidatePasteExpression(StringReference(L"123"), ViewMode::None, CategoryGroupType::None, -1, BitLength::BitLengthUnknown), + m_CopyPasteManager->ValidatePasteExpression( + StringReference(L"123"), ViewMode::None, CategoryGroupType::None, NumberBase::Unknown, BitLength::BitLengthUnknown), StringReference(L"NoOp"), L"Verify pasting without a ViewMode or Category is invalid"); }; @@ -96,48 +114,57 @@ namespace CalculatorUnitTests { vector results = {}; - vector oneOperand = { L"123456" }; - VERIFY_ARE_EQUAL(m_CopyPasteManager->ExtractOperands(L"123456", ViewMode::Standard), oneOperand); - oneOperand = { L"123^456" }; - VERIFY_ARE_EQUAL(m_CopyPasteManager->ExtractOperands(L"123^456", ViewMode::Standard), oneOperand); + auto oneOperand = ref new Vector(); + oneOperand->Append(L"123456"); - vector twoOperands = { L"123", L"456" }; - VERIFY_ARE_EQUAL(m_CopyPasteManager->ExtractOperands(L"123+456", ViewMode::Standard), twoOperands); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ExtractOperands(L"123-456", ViewMode::Standard), twoOperands); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ExtractOperands(L"123*456", ViewMode::Standard), twoOperands); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ExtractOperands(L"123/456", ViewMode::Standard), twoOperands); + VERIFY_VECTORS_ARE_EQUAL(CopyPasteManager::ExtractOperands(L"123456", ViewMode::Standard), oneOperand); + oneOperand->Clear(); + oneOperand->Append(L"123^456"); + VERIFY_VECTORS_ARE_EQUAL(CopyPasteManager::ExtractOperands(L"123^456", ViewMode::Standard), oneOperand); - vector expOperand = { L"123e456" }; - VERIFY_ARE_EQUAL(m_CopyPasteManager->ExtractOperands(L"123e456", ViewMode::Standard), expOperand); - expOperand = { L"123e4567" }; - VERIFY_ARE_EQUAL(m_CopyPasteManager->ExtractOperands(L"123e4567", ViewMode::Standard), expOperand); + auto twoOperands = ref new Vector(); + twoOperands->Append(L"123"); + twoOperands->Append(L"456"); + VERIFY_VECTORS_ARE_EQUAL(CopyPasteManager::ExtractOperands(L"123+456", ViewMode::Standard), twoOperands); + VERIFY_VECTORS_ARE_EQUAL(CopyPasteManager::ExtractOperands(L"123-456", ViewMode::Standard), twoOperands); + VERIFY_VECTORS_ARE_EQUAL(CopyPasteManager::ExtractOperands(L"123*456", ViewMode::Standard), twoOperands); + VERIFY_VECTORS_ARE_EQUAL(CopyPasteManager::ExtractOperands(L"123/456", ViewMode::Standard), twoOperands); - vector twoOperandsParens = { L"((45)", L"(-30))" }; - VERIFY_ARE_EQUAL(m_CopyPasteManager->ExtractOperands(L"((45)+(-30))", ViewMode::Scientific), twoOperandsParens); + auto expOperand = ref new Vector(); + expOperand->Append(L"123e456"); + VERIFY_VECTORS_ARE_EQUAL(CopyPasteManager::ExtractOperands(L"123e456", ViewMode::Standard), expOperand); + expOperand->Clear(); + expOperand->Append(L"123e4567"); + VERIFY_VECTORS_ARE_EQUAL(CopyPasteManager::ExtractOperands(L"123e4567", ViewMode::Standard), expOperand); + + auto twoOperandsParens = ref new Vector(); + twoOperandsParens->Append(L"((45)"); + twoOperandsParens->Append(L"(-30))"); + VERIFY_VECTORS_ARE_EQUAL(CopyPasteManager::ExtractOperands(L"((45)+(-30))", ViewMode::Scientific), twoOperandsParens); }; TEST_METHOD(ValidateExtractOperandsErrors) { - wstring exp_OperandLimit = L""; - for (int i = 0; i < m_CopyPasteManager->MaxOperandCount; i++) + auto exp_OperandLimit = ref new String(L""); + for (unsigned int i = 0; i < m_CopyPasteManager->MaxOperandCount; i++) { exp_OperandLimit += L"+1"; } VERIFY_ARE_EQUAL( - m_CopyPasteManager->ExtractOperands(exp_OperandLimit, ViewMode::Standard).size(), + CopyPasteManager::ExtractOperands(exp_OperandLimit, ViewMode::Standard)->Size, 100, L"Verify ExtractOperands handles up to MaxOperandCount operands"); exp_OperandLimit += L"+1"; VERIFY_ARE_EQUAL( - m_CopyPasteManager->ExtractOperands(exp_OperandLimit, ViewMode::Standard).size(), + CopyPasteManager::ExtractOperands(exp_OperandLimit, ViewMode::Standard)->Size, 0, L"Verify ExtractOperands returns empty vector on too many operands"); VERIFY_ARE_EQUAL( - m_CopyPasteManager->ExtractOperands(L"12e9999", ViewMode::Standard).size(), 1, L"Verify ExtractOperands handles up to 4 digit exponents"); + CopyPasteManager::ExtractOperands(L"12e9999", ViewMode::Standard)->Size, 1, L"Verify ExtractOperands handles up to 4 digit exponents"); VERIFY_ARE_EQUAL( - m_CopyPasteManager->ExtractOperands(L"12e10000", ViewMode::Standard).size(), + CopyPasteManager::ExtractOperands(L"12e10000", ViewMode::Standard)->Size, 0, L"Verify ExtractOperands returns empty vector when the exponent is too long"); }; @@ -145,164 +172,263 @@ namespace CalculatorUnitTests TEST_METHOD(ValidateExpressionRegExMatch) { VERIFY_IS_FALSE( - m_CopyPasteManager->ExpressionRegExMatch(vector{}, ViewMode::Standard, CategoryGroupType::Calculator, -1, BitLength::BitLengthUnknown), + m_CopyPasteManager->ExpressionRegExMatch( + ref new Vector(), ViewMode::Standard, CategoryGroupType::Calculator, NumberBase::Unknown, BitLength::BitLengthUnknown), L"Verify empty list of operands returns false."); VERIFY_IS_FALSE( m_CopyPasteManager->ExpressionRegExMatch( - vector{ L"123" }, ViewMode::None, CategoryGroupType::Calculator, -1, BitLength::BitLengthUnknown), + ref new Vector({ L"123" }), + ViewMode::None, + CategoryGroupType::Calculator, + NumberBase::Unknown, + BitLength::BitLengthUnknown), L"Verify invalid ViewMode/CategoryGroups return false."); VERIFY_IS_FALSE( m_CopyPasteManager->ExpressionRegExMatch( - vector{ L"123" }, ViewMode::Currency, CategoryGroupType::None, -1, BitLength::BitLengthUnknown), + ref new Vector({ L"123" }), + ViewMode::Currency, + CategoryGroupType::None, + NumberBase::Unknown, + BitLength::BitLengthUnknown), L"Verify invalid ViewMode/CategoryGroups return false."); Logger::WriteMessage(L"Verify operand lengths > max return false."); VERIFY_IS_FALSE(m_CopyPasteManager->ExpressionRegExMatch( - vector{ L"12345678901234567" }, ViewMode::Standard, CategoryGroupType::Calculator, -1, BitLength::BitLengthUnknown)); + ref new Vector({ L"12345678901234567" }), + ViewMode::Standard, + CategoryGroupType::Calculator, + NumberBase::Unknown, + BitLength::BitLengthUnknown)); VERIFY_IS_FALSE(m_CopyPasteManager->ExpressionRegExMatch( - vector{ L"123456789012345678901234567890123" }, ViewMode::Scientific, CategoryGroupType::Calculator, -1, BitLength::BitLengthUnknown)); + ref new Vector({ L"123456789012345678901234567890123" }), + ViewMode::Scientific, + CategoryGroupType::Calculator, + NumberBase::Unknown, + BitLength::BitLengthUnknown)); VERIFY_IS_FALSE(m_CopyPasteManager->ExpressionRegExMatch( - vector{ L"12345678901234567" }, ViewMode::None, CategoryGroupType::Converter, -1, BitLength::BitLengthUnknown)); + ref new Vector({ L"12345678901234567" }), + ViewMode::None, + CategoryGroupType::Converter, + NumberBase::Unknown, + BitLength::BitLengthUnknown)); VERIFY_IS_FALSE(m_CopyPasteManager->ExpressionRegExMatch( - vector{ L"11111111111111111" }, ViewMode::Programmer, CategoryGroupType::Calculator, HexBase, BitLength::BitLengthQWord)); - VERIFY_IS_FALSE(m_CopyPasteManager->ExpressionRegExMatch( - vector{ L"12345678901234567890" }, ViewMode::Programmer, CategoryGroupType::Calculator, DecBase, BitLength::BitLengthQWord)); - VERIFY_IS_FALSE(m_CopyPasteManager->ExpressionRegExMatch( - vector{ L"11111111111111111111111" }, ViewMode::Programmer, CategoryGroupType::Calculator, OctBase, BitLength::BitLengthQWord)); - VERIFY_IS_FALSE(m_CopyPasteManager->ExpressionRegExMatch( - vector{ L"10000000000000000000000000000000000000000000000000000000000000000" }, + ref new Vector({ L"11111111111111111" }), ViewMode::Programmer, CategoryGroupType::Calculator, - BinBase, + NumberBase::HexBase, + BitLength::BitLengthQWord)); + VERIFY_IS_FALSE(m_CopyPasteManager->ExpressionRegExMatch( + ref new Vector({ L"12345678901234567890" }), + ViewMode::Programmer, + CategoryGroupType::Calculator, + NumberBase::DecBase, + BitLength::BitLengthQWord)); + VERIFY_IS_FALSE(m_CopyPasteManager->ExpressionRegExMatch( + ref new Vector({ L"11111111111111111111111" }), + ViewMode::Programmer, + CategoryGroupType::Calculator, + NumberBase::OctBase, + BitLength::BitLengthQWord)); + VERIFY_IS_FALSE(m_CopyPasteManager->ExpressionRegExMatch( + ref new Vector({ L"10000000000000000000000000000000000000000000000000000000000000000" }), + ViewMode::Programmer, + CategoryGroupType::Calculator, + NumberBase::BinBase, BitLength::BitLengthQWord)); VERIFY_IS_FALSE( m_CopyPasteManager->ExpressionRegExMatch( - vector{ L"9223372036854775808" }, ViewMode::Programmer, CategoryGroupType::Calculator, DecBase, BitLength::BitLengthQWord), + ref new Vector({ L"9223372036854775808" }), + ViewMode::Programmer, + CategoryGroupType::Calculator, + NumberBase::DecBase, + BitLength::BitLengthQWord), L"Verify operand values > max return false."); VERIFY_IS_TRUE( m_CopyPasteManager->ExpressionRegExMatch( - vector{ L"((((((((((((((((((((123))))))))))))))))))))" }, + ref new Vector({ L"((((((((((((((((((((123))))))))))))))))))))" }), ViewMode::Scientific, CategoryGroupType::Calculator, - -1, + NumberBase::Unknown, BitLength::BitLengthUnknown), L"Verify sanitized operand is detected as within max length."); VERIFY_IS_TRUE( m_CopyPasteManager->ExpressionRegExMatch( - vector{ L"9223372036854775807" }, ViewMode::Programmer, CategoryGroupType::Calculator, DecBase, BitLength::BitLengthQWord), + ref new Vector({ L"9223372036854775807" }), + ViewMode::Programmer, + CategoryGroupType::Calculator, + NumberBase::DecBase, + BitLength::BitLengthQWord), L"Verify operand values == max return true."); Logger::WriteMessage(L"Verify all operands must match patterns."); VERIFY_IS_TRUE(m_CopyPasteManager->ExpressionRegExMatch( - vector{ L"123", L"456" }, ViewMode::Standard, CategoryGroupType::Calculator, -1, BitLength::BitLengthUnknown)); + ref new Vector({ L"123", L"456" }), + ViewMode::Standard, + CategoryGroupType::Calculator, + NumberBase::Unknown, + BitLength::BitLengthUnknown)); VERIFY_IS_TRUE(m_CopyPasteManager->ExpressionRegExMatch( - vector{ L"123", L"1e23" }, ViewMode::Standard, CategoryGroupType::Calculator, -1, BitLength::BitLengthUnknown)); + ref new Vector({ L"123", L"1e23" }), + ViewMode::Standard, + CategoryGroupType::Calculator, + NumberBase::Unknown, + BitLength::BitLengthUnknown)); VERIFY_IS_FALSE(m_CopyPasteManager->ExpressionRegExMatch( - vector{ L"123", L"fab10" }, ViewMode::Standard, CategoryGroupType::Calculator, -1, BitLength::BitLengthUnknown)); + ref new Vector({ L"123", L"fab10" }), + ViewMode::Standard, + CategoryGroupType::Calculator, + NumberBase::Unknown, + BitLength::BitLengthUnknown)); VERIFY_IS_TRUE( m_CopyPasteManager->ExpressionRegExMatch( - vector{ L"1.23e+456", L"1.23e456", L".23e+456", L"123e-456", L"12e2", L"12e+2", L"12e-2", L"-12e2", L"-12e+2", L"-12e-2" }, + ref new Vector( + { L"1.23e+456", L"1.23e456", L".23e+456", L"123e-456", L"12e2", L"12e+2", L"12e-2", L"-12e2", L"-12e+2", L"-12e-2" }), ViewMode::Scientific, CategoryGroupType::Calculator, - -1, + NumberBase::Unknown, BitLength::BitLengthUnknown), L"Verify exponents are accepted in scientific mode."); VERIFY_IS_FALSE( m_CopyPasteManager->ExpressionRegExMatch( - vector{ L"123", L"12345678901234567" }, ViewMode::Standard, CategoryGroupType::Calculator, -1, BitLength::BitLengthUnknown), + ref new Vector({ L"123", L"12345678901234567" }), + ViewMode::Standard, + CategoryGroupType::Calculator, + NumberBase::Unknown, + BitLength::BitLengthUnknown), L"Verify all operands must be within maxlength"); VERIFY_IS_FALSE( m_CopyPasteManager->ExpressionRegExMatch( - vector{ L"123", L"9223372036854775808" }, ViewMode::Programmer, CategoryGroupType::Calculator, DecBase, BitLength::BitLengthQWord), + ref new Vector({ L"123", L"9223372036854775808" }), + ViewMode::Programmer, + CategoryGroupType::Calculator, + NumberBase::DecBase, + BitLength::BitLengthQWord), L"Verify all operand must be within max value."); }; TEST_METHOD(ValidateGetMaxOperandLengthAndValue) { - pair standardModeMaximums = make_pair(m_CopyPasteManager->MaxStandardOperandLength, 0); - pair scientificModeMaximums = make_pair(m_CopyPasteManager->MaxScientificOperandLength, 0); - pair converterModeMaximums = make_pair(m_CopyPasteManager->MaxConverterInputLength, 0); - VERIFY_ARE_EQUAL( - m_CopyPasteManager->GetMaxOperandLengthAndValue(ViewMode::Standard, CategoryGroupType::None, -1, BitLength::BitLengthUnknown), - standardModeMaximums, + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Standard, CategoryGroupType::None, NumberBase::Unknown, BitLength::BitLengthUnknown), + m_CopyPasteManager->MaxStandardOperandLength, + 0, L"Verify Standard mode maximum values"); - VERIFY_ARE_EQUAL( - m_CopyPasteManager->GetMaxOperandLengthAndValue(ViewMode::Scientific, CategoryGroupType::None, -1, BitLength::BitLengthUnknown), - scientificModeMaximums, + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Scientific, CategoryGroupType::None, NumberBase::Unknown, BitLength::BitLengthUnknown), + m_CopyPasteManager->MaxScientificOperandLength, + 0, L"Verify Scientific mode maximum values"); - VERIFY_ARE_EQUAL( - m_CopyPasteManager->GetMaxOperandLengthAndValue(ViewMode::None, CategoryGroupType::Converter, -1, BitLength::BitLengthUnknown), - converterModeMaximums, + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::None, CategoryGroupType::Converter, NumberBase::Unknown, BitLength::BitLengthUnknown), + m_CopyPasteManager->MaxConverterInputLength, + 0, L"Verify Converter mode maximum values"); unsigned long long int ullQwordMax = UINT64_MAX; unsigned long long int ullDwordMax = UINT32_MAX; unsigned long long int ullWordMax = UINT16_MAX; unsigned long long int ullByteMax = UINT8_MAX; - Logger::WriteMessage(L"Verify Programmer Mode HexBase maximum values"); - VERIFY_ARE_EQUAL( - m_CopyPasteManager->GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, HexBase, BitLength::BitLengthQWord), - make_pair((size_t)16u, ullQwordMax)); - VERIFY_ARE_EQUAL( - m_CopyPasteManager->GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, HexBase, BitLength::BitLengthDWord), - make_pair((size_t)8u, ullDwordMax)); - VERIFY_ARE_EQUAL( - m_CopyPasteManager->GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, HexBase, BitLength::BitLengthWord), - make_pair((size_t)4u, ullWordMax)); - VERIFY_ARE_EQUAL( - m_CopyPasteManager->GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, HexBase, BitLength::BitLengthByte), - make_pair((size_t)2u, ullByteMax)); + Logger::WriteMessage(L"Verify Programmer Mode NumberBase::HexBase maximum values"); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::HexBase, BitLength::BitLengthQWord), + 16u, + ullQwordMax); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::HexBase, BitLength::BitLengthDWord), + 8u, + ullDwordMax); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::HexBase, BitLength::BitLengthWord), + 4u, + ullWordMax); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::HexBase, BitLength::BitLengthByte), + 2u, + ullByteMax); - Logger::WriteMessage(L"Verify Programmer Mode DecBase maximum values"); - VERIFY_ARE_EQUAL( - m_CopyPasteManager->GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, DecBase, BitLength::BitLengthQWord), - make_pair((size_t)19u, ullQwordMax >> 1)); - VERIFY_ARE_EQUAL( - m_CopyPasteManager->GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, DecBase, BitLength::BitLengthDWord), - make_pair((size_t)10u, ullDwordMax >> 1)); - VERIFY_ARE_EQUAL( - m_CopyPasteManager->GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, DecBase, BitLength::BitLengthWord), - make_pair((size_t)5u, ullWordMax >> 1)); - VERIFY_ARE_EQUAL( - m_CopyPasteManager->GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, DecBase, BitLength::BitLengthByte), - make_pair((size_t)3u, ullByteMax >> 1)); + Logger::WriteMessage(L"Verify Programmer Mode NumberBase::DecBase maximum values"); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::DecBase, BitLength::BitLengthQWord), + 19u, + ullQwordMax >> 1); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::DecBase, BitLength::BitLengthDWord), + 10u, + ullDwordMax >> 1); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::DecBase, BitLength::BitLengthWord), + 5u, + ullWordMax >> 1); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::DecBase, BitLength::BitLengthByte), + 3u, + ullByteMax >> 1); - Logger::WriteMessage(L"Verify Programmer Mode OctBase maximum values"); - VERIFY_ARE_EQUAL( - m_CopyPasteManager->GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, OctBase, BitLength::BitLengthQWord), - make_pair((size_t)22u, ullQwordMax)); - VERIFY_ARE_EQUAL( - m_CopyPasteManager->GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, OctBase, BitLength::BitLengthDWord), - make_pair((size_t)11u, ullDwordMax)); - VERIFY_ARE_EQUAL( - m_CopyPasteManager->GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, OctBase, BitLength::BitLengthWord), - make_pair((size_t)6u, ullWordMax)); - VERIFY_ARE_EQUAL( - m_CopyPasteManager->GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, OctBase, BitLength::BitLengthByte), - make_pair((size_t)3u, ullByteMax)); + Logger::WriteMessage(L"Verify Programmer Mode NumberBase::OctBase maximum values"); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::OctBase, BitLength::BitLengthQWord), + 22u, + ullQwordMax); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::OctBase, BitLength::BitLengthDWord), + 11u, + ullDwordMax); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::OctBase, BitLength::BitLengthWord), + 6u, + ullWordMax); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::OctBase, BitLength::BitLengthByte), + 3u, + ullByteMax); - Logger::WriteMessage(L"Verify Programmer Mode BinBase maximum values"); - VERIFY_ARE_EQUAL( - m_CopyPasteManager->GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, BinBase, BitLength::BitLengthQWord), - make_pair((size_t)64u, ullQwordMax)); - VERIFY_ARE_EQUAL( - m_CopyPasteManager->GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, BinBase, BitLength::BitLengthDWord), - make_pair((size_t)32u, ullDwordMax)); - VERIFY_ARE_EQUAL( - m_CopyPasteManager->GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, BinBase, BitLength::BitLengthWord), - make_pair((size_t)16u, ullWordMax)); - VERIFY_ARE_EQUAL( - m_CopyPasteManager->GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, BinBase, BitLength::BitLengthByte), - make_pair((size_t)8u, ullByteMax)); + Logger::WriteMessage(L"Verify Programmer Mode NumberBase::BinBase maximum values"); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::BinBase, BitLength::BitLengthQWord), + 64u, + ullQwordMax); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::BinBase, BitLength::BitLengthDWord), + 32u, + ullDwordMax); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::BinBase, BitLength::BitLengthWord), + 16u, + ullWordMax); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::BinBase, BitLength::BitLengthByte), + 8u, + ullByteMax); Logger::WriteMessage(L"Verify invalid ViewModes/Categories return 0 for max values"); - VERIFY_ARE_EQUAL( - m_CopyPasteManager->GetMaxOperandLengthAndValue(ViewMode::None, CategoryGroupType::None, -1, BitLength::BitLengthUnknown), - make_pair((size_t)0u, 0ull)); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::None, CategoryGroupType::None, NumberBase::Unknown, BitLength::BitLengthUnknown), + 0u, + 0ull); }; TEST_METHOD(ValidateSanitizeOperand) @@ -326,89 +452,103 @@ namespace CalculatorUnitTests TEST_METHOD(ValidatePrefixCurrencySymbols) { // ¥5 - VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromWstring(L"\u00A5\u0035"), L"5"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromString(L"\u00A5\u0035"), L"5"); // ¤5 - VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromWstring(L"\u00A4\u0035"), L"5"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromString(L"\u00A4\u0035"), L"5"); // ₵5 - VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromWstring(L"\u20B5\u0035"), L"5"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromString(L"\u20B5\u0035"), L"5"); // $5 - VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromWstring(L"\u0024\u0035"), L"5"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromString(L"\u0024\u0035"), L"5"); // ₡5 - VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromWstring(L"\u20A1\u0035"), L"5"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromString(L"\u20A1\u0035"), L"5"); // ₩5 - VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromWstring(L"\u20A9\u0035"), L"5"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromString(L"\u20A9\u0035"), L"5"); // ₪5 - VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromWstring(L"\u20AA\u0035"), L"5"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromString(L"\u20AA\u0035"), L"5"); // ₦5 - VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromWstring(L"\u20A6\u0035"), L"5"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromString(L"\u20A6\u0035"), L"5"); // ₹5 - VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromWstring(L"\u20B9\u0035"), L"5"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromString(L"\u20B9\u0035"), L"5"); // £5 - VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromWstring(L"\u00A3\u0035"), L"5"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromString(L"\u00A3\u0035"), L"5"); // €5 - VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromWstring(L"\u20AC\u0035"), L"5"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromString(L"\u20AC\u0035"), L"5"); }; TEST_METHOD(ValidateTryOperandToULL) { - unsigned long long int result = 0; + IBox ^ result = nullptr; - Logger::WriteMessage(L"Verify TryOperandToULL HexBase conversion"); - VERIFY_IS_TRUE(m_CopyPasteManager->TryOperandToULL(L"1234", HexBase, result)); - VERIFY_ARE_EQUAL(result, 0x1234ull); - VERIFY_IS_TRUE(m_CopyPasteManager->TryOperandToULL(L"FF", HexBase, result)); - VERIFY_ARE_EQUAL(result, 0xFFull); - VERIFY_IS_TRUE(m_CopyPasteManager->TryOperandToULL(L"FFFFFFFFFFFFFFFF", HexBase, result)); - VERIFY_ARE_EQUAL(result, 0xFFFF'FFFF'FFFF'FFFF); - VERIFY_IS_TRUE(m_CopyPasteManager->TryOperandToULL(L"0xFFFFFFFFFFFFFFFF", HexBase, result)); - VERIFY_ARE_EQUAL(result, 0xFFFF'FFFF'FFFF'FFFF); - VERIFY_IS_TRUE(m_CopyPasteManager->TryOperandToULL(L"0XFFFFFFFFFFFFFFFF", HexBase, result)); - VERIFY_ARE_EQUAL(result, 0xFFFF'FFFF'FFFF'FFFF); - VERIFY_IS_TRUE(m_CopyPasteManager->TryOperandToULL(L"0X0FFFFFFFFFFFFFFFF", HexBase, result)); - VERIFY_ARE_EQUAL(result, 0xFFFF'FFFF'FFFF'FFFF); + Logger::WriteMessage(L"Verify TryOperandToULL NumberBase::HexBase conversion"); + result = CopyPasteManager::TryOperandToULL(L"1234", NumberBase::HexBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0x1234ull); + result = CopyPasteManager::TryOperandToULL(L"FF", NumberBase::HexBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0xFFull); + result = CopyPasteManager::TryOperandToULL(L"FFFFFFFFFFFFFFFF", NumberBase::HexBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0xFFFF'FFFF'FFFF'FFFF); + result = CopyPasteManager::TryOperandToULL(L"0xFFFFFFFFFFFFFFFF", NumberBase::HexBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0xFFFF'FFFF'FFFF'FFFF); + result = CopyPasteManager::TryOperandToULL(L"0XFFFFFFFFFFFFFFFF", NumberBase::HexBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0xFFFF'FFFF'FFFF'FFFF); + result = CopyPasteManager::TryOperandToULL(L"0X0FFFFFFFFFFFFFFFF", NumberBase::HexBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0xFFFF'FFFF'FFFF'FFFF); - Logger::WriteMessage(L"Verify TryOperandToULL DecBase conversion"); - VERIFY_IS_TRUE(m_CopyPasteManager->TryOperandToULL(L"1234", DecBase, result)); - VERIFY_ARE_EQUAL(result, 1234ull); - VERIFY_IS_TRUE(m_CopyPasteManager->TryOperandToULL(L"18446744073709551615", DecBase, result)); - VERIFY_ARE_EQUAL(result, 0xFFFF'FFFF'FFFF'FFFF); - VERIFY_IS_TRUE(m_CopyPasteManager->TryOperandToULL(L"018446744073709551615", DecBase, result)); - VERIFY_ARE_EQUAL(result, 0xFFFF'FFFF'FFFF'FFFF); + Logger::WriteMessage(L"Verify TryOperandToULL NumberBase::DecBase conversion"); + result = CopyPasteManager::TryOperandToULL(L"1234", NumberBase::DecBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 1234ull); + result = CopyPasteManager::TryOperandToULL(L"18446744073709551615", NumberBase::DecBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0xFFFF'FFFF'FFFF'FFFF); + result = CopyPasteManager::TryOperandToULL(L"018446744073709551615", NumberBase::DecBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0xFFFF'FFFF'FFFF'FFFF); - Logger::WriteMessage(L"Verify TryOperandToULL OctBase conversion"); - VERIFY_IS_TRUE(m_CopyPasteManager->TryOperandToULL(L"777", OctBase, result)); - VERIFY_ARE_EQUAL(result, 0777ull); - VERIFY_IS_TRUE(m_CopyPasteManager->TryOperandToULL(L"0777", OctBase, result)); - VERIFY_ARE_EQUAL(result, 0777ull); - VERIFY_IS_TRUE(m_CopyPasteManager->TryOperandToULL(L"1777777777777777777777", OctBase, result)); - VERIFY_ARE_EQUAL(result, 0xFFFF'FFFF'FFFF'FFFF); - VERIFY_IS_TRUE(m_CopyPasteManager->TryOperandToULL(L"01777777777777777777777", OctBase, result)); - VERIFY_ARE_EQUAL(result, 0xFFFF'FFFF'FFFF'FFFF); + Logger::WriteMessage(L"Verify TryOperandToULL NumberBase::OctBase conversion"); + result = CopyPasteManager::TryOperandToULL(L"777", NumberBase::OctBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0777ull); + result = CopyPasteManager::TryOperandToULL(L"0777", NumberBase::OctBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0777ull); + result = CopyPasteManager::TryOperandToULL(L"1777777777777777777777", NumberBase::OctBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0xFFFF'FFFF'FFFF'FFFF); + result = CopyPasteManager::TryOperandToULL(L"01777777777777777777777", NumberBase::OctBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0xFFFF'FFFF'FFFF'FFFF); - Logger::WriteMessage(L"Verify TryOperandToULL BinBase conversion"); - VERIFY_IS_TRUE(m_CopyPasteManager->TryOperandToULL(L"1111", BinBase, result)); - VERIFY_ARE_EQUAL(result, 0b1111ull); - VERIFY_IS_TRUE(m_CopyPasteManager->TryOperandToULL(L"0010", BinBase, result)); - VERIFY_ARE_EQUAL(result, 0b10ull); - VERIFY_IS_TRUE(m_CopyPasteManager->TryOperandToULL(L"1111111111111111111111111111111111111111111111111111111111111111", BinBase, result)); - VERIFY_ARE_EQUAL(result, 0xFFFF'FFFF'FFFF'FFFF); - VERIFY_IS_TRUE(m_CopyPasteManager->TryOperandToULL(L"01111111111111111111111111111111111111111111111111111111111111111", BinBase, result)); - VERIFY_ARE_EQUAL(result, 0xFFFF'FFFF'FFFF'FFFF); - - Logger::WriteMessage(L"Verify TryOperandToULL invalid numberBase defaults to DecBase"); - VERIFY_IS_TRUE(m_CopyPasteManager->TryOperandToULL(L"1234", 128, result)); - VERIFY_ARE_EQUAL(result, 1234ull); + Logger::WriteMessage(L"Verify TryOperandToULL NumberBase::BinBase conversion"); + result = CopyPasteManager::TryOperandToULL(L"1111", NumberBase::BinBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0b1111ull); + result = CopyPasteManager::TryOperandToULL(L"0010", NumberBase::BinBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0b10ull); + result = CopyPasteManager::TryOperandToULL(L"1111111111111111111111111111111111111111111111111111111111111111", NumberBase::BinBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0xFFFF'FFFF'FFFF'FFFF); + result = CopyPasteManager::TryOperandToULL(L"01111111111111111111111111111111111111111111111111111111111111111", NumberBase::BinBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0xFFFF'FFFF'FFFF'FFFF); Logger::WriteMessage(L"Verify TryOperandToULL returns false when input is invalid or strtoull throws exceptions"); // Max values + 1 - VERIFY_IS_FALSE(m_CopyPasteManager->TryOperandToULL(L"0xFFFFFFFFFFFFFFFFF1", HexBase, result)); - VERIFY_IS_FALSE(m_CopyPasteManager->TryOperandToULL(L"18446744073709551616", DecBase, result)); - VERIFY_IS_FALSE(m_CopyPasteManager->TryOperandToULL(L"2000000000000000000000", OctBase, result)); - VERIFY_IS_FALSE(m_CopyPasteManager->TryOperandToULL(L"11111111111111111111111111111111111111111111111111111111111111111", BinBase, result)); + VERIFY_IS_NULL(CopyPasteManager::TryOperandToULL(L"0xFFFFFFFFFFFFFFFFF1", NumberBase::HexBase)); + VERIFY_IS_NULL(CopyPasteManager::TryOperandToULL(L"18446744073709551616", NumberBase::DecBase)); + VERIFY_IS_NULL(CopyPasteManager::TryOperandToULL(L"2000000000000000000000", NumberBase::OctBase)); + VERIFY_IS_NULL( + CopyPasteManager::TryOperandToULL(L"11111111111111111111111111111111111111111111111111111111111111111", NumberBase::BinBase)); // Invalid values/characters - VERIFY_IS_FALSE(m_CopyPasteManager->TryOperandToULL(L"-1", DecBase, result)); - VERIFY_IS_FALSE(m_CopyPasteManager->TryOperandToULL(L"5555", BinBase, result)); - VERIFY_IS_FALSE(m_CopyPasteManager->TryOperandToULL(L"xyz", BinBase, result)); + VERIFY_IS_NULL(CopyPasteManager::TryOperandToULL(L"-1", NumberBase::DecBase)); + VERIFY_IS_NULL(CopyPasteManager::TryOperandToULL(L"5555", NumberBase::BinBase)); + VERIFY_IS_NULL(CopyPasteManager::TryOperandToULL(L"xyz", NumberBase::BinBase)); }; TEST_METHOD(ValidateStandardScientificOperandLength) @@ -423,130 +563,130 @@ namespace CalculatorUnitTests TEST_METHOD(ValidateProgrammerOperandLength) { - VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"1001", BinBase), 4); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"1001b", BinBase), 4); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"1001B", BinBase), 4); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0b1001", BinBase), 4); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0B1001", BinBase), 4); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0y1001", BinBase), 4); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0Y1001", BinBase), 4); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0b", BinBase), 1); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"1001", NumberBase::BinBase), 4); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"1001b", NumberBase::BinBase), 4); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"1001B", NumberBase::BinBase), 4); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0b1001", NumberBase::BinBase), 4); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0B1001", NumberBase::BinBase), 4); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0y1001", NumberBase::BinBase), 4); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0Y1001", NumberBase::BinBase), 4); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0b", NumberBase::BinBase), 1); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"123456", OctBase), 6); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0t123456", OctBase), 6); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0T123456", OctBase), 6); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0o123456", OctBase), 6); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0O123456", OctBase), 6); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"123456", NumberBase::OctBase), 6); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0t123456", NumberBase::OctBase), 6); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0T123456", NumberBase::OctBase), 6); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0o123456", NumberBase::OctBase), 6); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0O123456", NumberBase::OctBase), 6); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"", DecBase), 0); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"-", DecBase), 0); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"12345", DecBase), 5); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"-12345", DecBase), 5); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0n12345", DecBase), 5); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0N12345", DecBase), 5); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"", NumberBase::DecBase), 0); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"-", NumberBase::DecBase), 0); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"12345", NumberBase::DecBase), 5); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"-12345", NumberBase::DecBase), 5); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0n12345", NumberBase::DecBase), 5); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0N12345", NumberBase::DecBase), 5); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"123ABC", HexBase), 6); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0x123ABC", HexBase), 6); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0X123ABC", HexBase), 6); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"123ABCh", HexBase), 6); - VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"123ABCH", HexBase), 6); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"123ABC", NumberBase::HexBase), 6); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0x123ABC", NumberBase::HexBase), 6); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0X123ABC", NumberBase::HexBase), 6); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"123ABCh", NumberBase::HexBase), 6); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"123ABCH", NumberBase::HexBase), 6); }; private: CopyPasteManager ^ m_CopyPasteManager; String^ ValidateStandardPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Standard, -1/*number base*/, BitLength::BitLengthUnknown); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Standard, NumberBase::Unknown, BitLength::BitLengthUnknown); } String^ ValidateScientificPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Scientific, -1/*number base*/, BitLength::BitLengthUnknown); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Scientific, NumberBase::Unknown, BitLength::BitLengthUnknown); } String^ ValidateConverterPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::None, CategoryGroupType::Converter, -1/*number base*/, BitLength::BitLengthUnknown); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::None, CategoryGroupType::Converter, NumberBase::Unknown, BitLength::BitLengthUnknown); } String^ ValidateProgrammerHexQwordPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, HexBase/*number base*/, BitLength::BitLengthQWord); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::HexBase, BitLength::BitLengthQWord); } String^ ValidateProgrammerHexDwordPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, HexBase/*number base*/, BitLength::BitLengthDWord); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::HexBase, BitLength::BitLengthDWord); } String^ ValidateProgrammerHexWordPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, HexBase/*number base*/, BitLength::BitLengthWord); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::HexBase, BitLength::BitLengthWord); } String^ ValidateProgrammerHexBytePasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, HexBase/*number base*/, BitLength::BitLengthByte); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::HexBase, BitLength::BitLengthByte); } String^ ValidateProgrammerDecQwordPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, DecBase/*number base*/, BitLength::BitLengthQWord); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::DecBase, BitLength::BitLengthQWord); } String^ ValidateProgrammerDecDwordPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, DecBase/*number base*/, BitLength::BitLengthDWord); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::DecBase, BitLength::BitLengthDWord); } String^ ValidateProgrammerDecWordPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, DecBase/*number base*/, BitLength::BitLengthWord); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::DecBase, BitLength::BitLengthWord); } String^ ValidateProgrammerDecBytePasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, DecBase/*number base*/, BitLength::BitLengthByte); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::DecBase, BitLength::BitLengthByte); } String^ ValidateProgrammerOctQwordPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, OctBase/*number base*/, BitLength::BitLengthQWord); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::OctBase, BitLength::BitLengthQWord); } String^ ValidateProgrammerOctDwordPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, OctBase/*number base*/, BitLength::BitLengthDWord); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::OctBase, BitLength::BitLengthDWord); } String^ ValidateProgrammerOctWordPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, OctBase/*number base*/, BitLength::BitLengthWord); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::OctBase, BitLength::BitLengthWord); } String^ ValidateProgrammerOctBytePasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, OctBase/*number base*/, BitLength::BitLengthByte); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::OctBase, BitLength::BitLengthByte); } String^ ValidateProgrammerBinQwordPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, BinBase/*number base*/, BitLength::BitLengthQWord); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::BinBase, BitLength::BitLengthQWord); } String^ ValidateProgrammerBinDwordPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, BinBase/*number base*/, BitLength::BitLengthDWord); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::BinBase, BitLength::BitLengthDWord); } String^ ValidateProgrammerBinWordPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, BinBase/*number base*/, BitLength::BitLengthWord); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::BinBase, BitLength::BitLengthWord); } String^ ValidateProgrammerBinBytePasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, BinBase/*number base*/, BitLength::BitLengthByte); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::BinBase, BitLength::BitLengthByte); } }; @@ -587,7 +727,8 @@ namespace CalculatorUnitTests void CopyPasteManagerTest::FunctionalCopyPasteTest() { // Doesn't have test where converter is involved. Will add such a test later. - StandardCalculatorViewModel ^ scvm = ref new StandardCalculatorViewModel(); + StandardCalculatorViewModel ^ scvm = nullptr; + scvm = ref new StandardCalculatorViewModel(); scvm->IsStandard = true; String ^ inputs[] = { L"123", L"12345", L"123+456", L"1,234", L"1 2 3", L"\n\r1,234\n", L"\n 1+\n2 ", L"1\"2" }; diff --git a/src/CalculatorUnitTests/Helpers.h b/src/CalculatorUnitTests/Helpers.h index 01b449e..672dd55 100644 --- a/src/CalculatorUnitTests/Helpers.h +++ b/src/CalculatorUnitTests/Helpers.h @@ -1,10 +1,11 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" #pragma once #include "CalcViewModel/Common/CalculatorButtonUser.h" +#include namespace CalculatorUnitTests { @@ -95,3 +96,15 @@ namespace CalculatorUnitTests { \ Assert::IsTrue(__expectedGreater >= __expectedLess, __VA_ARGS__); \ } + +template +void VERIFY_VECTORS_ARE_EQUAL(Windows::Foundation::Collections::IVector ^ vecA, Windows::Foundation::Collections::IVector ^ vecB, ...) +{ + if (vecA->Size != vecB->Size) + Assert::Fail(); + + for (unsigned int i = 0; i < vecA->Size; ++i) + { + VERIFY_ARE_EQUAL(vecA->GetAt(i), vecB->GetAt(i), __VA_ARGS__); + } +}; diff --git a/src/CalculatorUnitTests/StandardViewModelUnitTests.cpp b/src/CalculatorUnitTests/StandardViewModelUnitTests.cpp index e882ace..7101741 100644 --- a/src/CalculatorUnitTests/StandardViewModelUnitTests.cpp +++ b/src/CalculatorUnitTests/StandardViewModelUnitTests.cpp @@ -24,7 +24,9 @@ namespace CalculatorUnitTests void CompareVector(IVector ^ vecA, IVector ^ vecB) { if (vecA->Size != vecB->Size) + { Assert::Fail(); + } for (unsigned int i = 0; i < vecA->Size; ++i) {