diff --git a/src/CalcViewModel/Common/CopyPasteManager.cpp b/src/CalcViewModel/Common/CopyPasteManager.cpp index dbcded5..ae24aad 100644 --- a/src/CalcViewModel/Common/CopyPasteManager.cpp +++ b/src/CalcViewModel/Common/CopyPasteManager.cpp @@ -310,6 +310,9 @@ bool CopyPasteManager::ExpressionRegExMatch( if (operandMatched) { + // Remember the sign of the operand + bool isNegativeValue = operand->Data()[0] == L'-'; + // 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. auto operandValue = SanitizeOperand(operand); @@ -332,7 +335,11 @@ bool CopyPasteManager::ExpressionRegExMatch( break; } - if (operandAsULL->Value > maxOperandLengthAndValue.maxValue) + // Calculate how much we exceed the maxValue. + // In case we exceed it for 1 only, and working with negative number - that's a corner case for max signed values (e.g. -32768) + bool isOverflow = operandAsULL->Value > maxOperandLengthAndValue.maxValue; + bool isMaxNegativeValue = operandAsULL->Value - 1 == maxOperandLengthAndValue.maxValue; + if (isOverflow && !(isNegativeValue && isMaxNegativeValue)) { expMatched = false; break; diff --git a/src/CalculatorUITestFramework/CalculatorResults.cs b/src/CalculatorUITestFramework/CalculatorResults.cs index a2c23ad..9371fa1 100644 --- a/src/CalculatorUITestFramework/CalculatorResults.cs +++ b/src/CalculatorUITestFramework/CalculatorResults.cs @@ -3,6 +3,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using OpenQA.Selenium.Appium.Windows; using System; +using OpenQA.Selenium.Interactions; namespace CalculatorUITestFramework { @@ -12,6 +13,8 @@ public class CalculatorResults private WindowsElement CalculatorAlwaysOnTopResults => this.session.TryFindElementByAccessibilityId("CalculatorAlwaysOnTopResults"); private WindowsElement CalculatorResult => this.session.TryFindElementByAccessibilityId("CalculatorResults"); private WindowsElement CalculatorExpression => this.session.TryFindElementByAccessibilityId("CalculatorExpression"); + private WindowsElement MenuItemCopy => this.session.TryFindElementByAccessibilityId("CopyMenuItem"); + private WindowsElement MenuItemPaste => this.session.TryFindElementByAccessibilityId("PasteMenuItem"); /// /// Gets the text from the display control in AoT mode and removes the narrator text that is not displayed in the UI. @@ -61,5 +64,33 @@ public void IsResultsExpressionClear() throw new Exception("The Calculator Expression is not clear"); } } + + /// + /// Opens the context menu in order to be able to click its items + /// + private void OpenContextMenu() + { + Actions actions = new Actions(CalculatorResult.WrappedDriver); + // It is important to move not to the centre in order to avoid click on the text + actions.MoveToElement(CalculatorResult, 1,1).ContextClick().Perform(); + } + + /// + /// Opens the context menu and clicks the "Copy" item there + /// + public void ContextMenuItemCopyClick() + { + OpenContextMenu(); + MenuItemCopy.Click(); + } + + /// + /// Opens the context menu and clicks the "Paste" item there + /// + public void ContextMenuItemPasteClick() + { + OpenContextMenu(); + MenuItemPaste.Click(); + } } } diff --git a/src/CalculatorUITests/ProgrammerModeFunctionalTests.cs b/src/CalculatorUITests/ProgrammerModeFunctionalTests.cs index 004292a..e5ca991 100644 --- a/src/CalculatorUITests/ProgrammerModeFunctionalTests.cs +++ b/src/CalculatorUITests/ProgrammerModeFunctionalTests.cs @@ -4,9 +4,7 @@ using CalculatorUITestFramework; using Microsoft.VisualStudio.TestTools.UnitTesting; using OpenQA.Selenium; -using OpenQA.Selenium.Appium.Windows; using System; -using System.Collections.Generic; namespace CalculatorUITests { @@ -890,5 +888,95 @@ public void ThroughCarry_Operator_Hex_RightShift() Assert.AreEqual("8 0 8", page.CalculatorResults.GetCalculatorResultText()); } #endregion + + /// + /// Copy and Paste the numbers into/from the calculator + /// + #region Copy-Paste operations + [TestMethod] + [Priority(1)] + public void Copy_And_Paste_Simple_Number() + { + page.ProgrammerOperators.BitFlip.Click(); + page.ProgrammerOperators.Bit1.Click(); + page.CalculatorResults.ContextMenuItemCopyClick(); + page.ProgrammerOperators.FullKeypad.Click(); + page.StandardOperators.ClearEntryButton.Click(); + page.CalculatorResults.ContextMenuItemPasteClick(); + Assert.AreEqual("2", page.CalculatorResults.GetCalculatorResultText()); + } + + [TestMethod] + [Priority(1)] + public void Copy_And_Paste_Invalid_Number() + { + page.ProgrammerOperators.BitFlip.Click(); + page.ProgrammerOperators.Bit63.Click(); + page.CalculatorResults.ContextMenuItemCopyClick(); + page.ProgrammerOperators.FullKeypad.Click(); + page.StandardOperators.ClearEntryButton.Click(); + page.ProgrammerOperators.QWordButton.Click(); + page.CalculatorResults.ContextMenuItemPasteClick(); + Assert.AreEqual("Invalid input", page.CalculatorResults.GetCalculatorResultText()); + } + + [TestMethod] + [Priority(1)] + public void Copy_And_Paste_Big_QWord_Number() + { + page.ProgrammerOperators.BitFlip.Click(); + page.ProgrammerOperators.Bit63.Click(); + page.CalculatorResults.ContextMenuItemCopyClick(); + page.ProgrammerOperators.FullKeypad.Click(); + page.StandardOperators.ClearEntryButton.Click(); + page.CalculatorResults.ContextMenuItemPasteClick(); + Assert.AreEqual("-9,223,372,036,854,775,808", page.CalculatorResults.GetCalculatorResultText()); + } + + [TestMethod] + [Priority(1)] + public void Copy_And_Paste_Big_DWord_Number() + { + page.ProgrammerOperators.QWordButton.Click(); + page.ProgrammerOperators.BitFlip.Click(); + page.ProgrammerOperators.Bit31.Click(); + page.CalculatorResults.ContextMenuItemCopyClick(); + page.ProgrammerOperators.FullKeypad.Click(); + page.StandardOperators.ClearEntryButton.Click(); + page.CalculatorResults.ContextMenuItemPasteClick(); + Assert.AreEqual("-2,147,483,648", page.CalculatorResults.GetCalculatorResultText()); + } + + [TestMethod] + [Priority(1)] + public void Copy_And_Paste_Big_Word_Number() + { + page.ProgrammerOperators.QWordButton.Click(); + page.ProgrammerOperators.DWordButton.Click(); + page.ProgrammerOperators.BitFlip.Click(); + page.ProgrammerOperators.Bit15.Click(); + page.CalculatorResults.ContextMenuItemCopyClick(); + page.ProgrammerOperators.FullKeypad.Click(); + page.StandardOperators.ClearEntryButton.Click(); + page.CalculatorResults.ContextMenuItemPasteClick(); + Assert.AreEqual("-32,768", page.CalculatorResults.GetCalculatorResultText()); + } + + [TestMethod] + [Priority(1)] + public void Copy_And_Paste_Big_Byte_Number() + { + page.ProgrammerOperators.QWordButton.Click(); + page.ProgrammerOperators.DWordButton.Click(); + page.ProgrammerOperators.WordButton.Click(); + page.ProgrammerOperators.BitFlip.Click(); + page.ProgrammerOperators.Bit7.Click(); + page.CalculatorResults.ContextMenuItemCopyClick(); + page.ProgrammerOperators.FullKeypad.Click(); + page.StandardOperators.ClearEntryButton.Click(); + page.CalculatorResults.ContextMenuItemPasteClick(); + Assert.AreEqual("-128", page.CalculatorResults.GetCalculatorResultText()); + } + #endregion } } diff --git a/src/CalculatorUnitTests/CopyPasteManagerTest.cpp b/src/CalculatorUnitTests/CopyPasteManagerTest.cpp index ee9eb1d..1b800f8 100644 --- a/src/CalculatorUnitTests/CopyPasteManagerTest.cpp +++ b/src/CalculatorUnitTests/CopyPasteManagerTest.cpp @@ -261,6 +261,14 @@ namespace CalculatorUnitTests NumberBase::DecBase, BitLength::BitLengthQWord), L"Verify operand values == max return true."); + VERIFY_IS_TRUE( + m_CopyPasteManager->ExpressionRegExMatch( + ref new Vector({ L"-9223372036854775808" }), + ViewMode::Programmer, + CategoryGroupType::Calculator, + NumberBase::DecBase, + BitLength::BitLengthQWord), + L"Verify operand values == max negative return true."); Logger::WriteMessage(L"Verify all operands must match patterns."); VERIFY_IS_TRUE(m_CopyPasteManager->ExpressionRegExMatch( @@ -950,6 +958,7 @@ namespace CalculatorUnitTests L"aef", L"ABab", L"A1a3" /*within boundary*/, + L"FFFF" /*boundary condition: max allowed number*/, L"0x1234", L"0xab12", L"0X1234", @@ -1046,7 +1055,7 @@ namespace CalculatorUnitTests L"123*4*-3", L"123*+4*-3", L"9223372036854775807", - L"-9223372036854775807" /*boundary condition: max/min allowed number*/, + L"-9223372036854775808" /*boundary condition: max/min allowed number*/, L"0n1234", L"0N1234", L"1234u", @@ -1069,6 +1078,7 @@ namespace CalculatorUnitTests L"xyz", L"ABab", L"e+234", + L"9223372036854775808" /*boundary condition: greater than max allowed number 9223372036854775807*/, L"9223372036854775809" /*boundary condition: greater than max allowed number 9223372036854775807*/, L"SIN(2)", L"-0n123", @@ -1145,7 +1155,8 @@ namespace CalculatorUnitTests L"123*4*-3", L"123*+4*-3", L"32767", - L"-32767" /*boundary condition: max/min allowed number*/, + L"-32767", + L"-32768" /*boundary condition: max/min allowed number*/, L"0n1234", L"0N1234", L"1234u", @@ -1208,7 +1219,8 @@ namespace CalculatorUnitTests { String ^ qwordPositiveInput[] = { L"123", L"123+456", L"1,234", L"1 2 3", L"1'2'3'4", L"1_2_3_4", L"\n\r1,234\n", L"\f\n1+2\t\r\v\x85", L"\n 1+\n2 ", L"1\"2", L"(123)+(456)", L"0t1234", L"0T1234", L"0o1234", L"0O1234", L"1234u", - L"1234ul", L"1234ULL", L"2+2=", L"2+2= ", L"127%71" }; + L"1234ul", L"1234ULL", L"2+2=", L"2+2= ", + L"127%71", L"1777777777777777777777" /*boundary condition: the max allowed number*/ }; String ^ qwordNegativeInput[] = { L"+123", L"1.23", L"1''2", @@ -1226,6 +1238,7 @@ namespace CalculatorUnitTests L"ABab", L"e+234", L"12345678901234567890123" /*boundary condition: greater than max allowed digits 22*/, + L"2000000000000000000000" /*boundary condition: greater than max allowed number*/, L"SIN(2)", L"123+-234", L"0ot1234", @@ -1260,6 +1273,7 @@ namespace CalculatorUnitTests L"ABab", L"e+234", L"377777777771" /*boundary condition: greater than max allowed number 37777777777*/, + L"40000000000" /*boundary condition: greater than max allowed number 37777777777*/, L"SIN(2)", L"123+-234", L"0ot1234", @@ -1303,6 +1317,7 @@ namespace CalculatorUnitTests L"ABab", L"e+234", L"1777771" /*boundary condition: greater than max allowed number 177777*/, + L"200000" /*boundary condition: greater than max allowed number 177777*/, L"SIN(2)", L"123+-234", L"0ot1234", @@ -1332,6 +1347,7 @@ namespace CalculatorUnitTests L"ABab", L"e+24", L"477" /*boundary condition: greater than max allowed number 377*/, + L"400" /*boundary condition: greater than max allowed number 377*/, L"SIN(2)", L"123+-34", L"0ot123", @@ -1497,7 +1513,8 @@ namespace CalculatorUnitTests String ^ bytePositiveInput[] = { L"100", L"100+101", L"1,001", L"1 0 1", L"1'0'0'1", L"1_0_0_1", L"\n\r1,010\n", L"\n 1+\n1 ", L"1\"1", L"(101)+(10)", L"0b1001", L"0B1111", L"0y1001", L"0Y1001", - L"1100b", L"1101B", L"1111u", L"1111ul", L"1111ULL", L"10100010" /*boundary condition: max allowed number*/ }; + L"1100b", L"1101B", L"1111u", L"1111ul", L"1111ULL", L"10100010", + L"11111111" /*boundary condition: max allowed number*/ }; String ^ byteNegativeInput[] = { L"+10101", L"1.01", L"1''0", @@ -1524,6 +1541,7 @@ namespace CalculatorUnitTests L"1111uu", L"1111ulll", L"101000101" /*boundary condition: greater than max allowed digits 8*/, + L"100000000" /*boundary condition: greater than max allowed value*/, L"SIN(01010)", L"10+-1010101" };