mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 09:46:54 +02:00
[PT Run][Calculator] Input validation improvements (#20067)
* improve input validation * update test * update tests * simplify test case * fix devision by zero check
This commit is contained in:
@@ -174,6 +174,8 @@ namespace Microsoft.PowerToys.Run.Plugin.Calculator.UnitTests
|
|||||||
[DataRow("abcde", false)]
|
[DataRow("abcde", false)]
|
||||||
[DataRow("1 + 2 +", false)]
|
[DataRow("1 + 2 +", false)]
|
||||||
[DataRow("1+2*", false)]
|
[DataRow("1+2*", false)]
|
||||||
|
[DataRow("1+2/", false)]
|
||||||
|
[DataRow("1+2%", false)]
|
||||||
[DataRow("1 && 3 &&", false)]
|
[DataRow("1 && 3 &&", false)]
|
||||||
[DataRow("sqrt( 36)", true)]
|
[DataRow("sqrt( 36)", true)]
|
||||||
[DataRow("max 4", false)]
|
[DataRow("max 4", false)]
|
||||||
@@ -220,6 +222,8 @@ namespace Microsoft.PowerToys.Run.Plugin.Calculator.UnitTests
|
|||||||
new object[] { "sign(2)", +1M },
|
new object[] { "sign(2)", +1M },
|
||||||
new object[] { "abs(-2)", 2M },
|
new object[] { "abs(-2)", 2M },
|
||||||
new object[] { "abs(2)", 2M },
|
new object[] { "abs(2)", 2M },
|
||||||
|
new object[] { "0+(1*2)/(0+1)", 2M }, // Validate that division by "(0+1)" is not interpret as division by zero.
|
||||||
|
new object[] { "0+(1*2)/0.5", 4M }, // Validate that division by number with decimal digits is not interpret as division by zero.
|
||||||
};
|
};
|
||||||
|
|
||||||
[DataTestMethod]
|
[DataTestMethod]
|
||||||
@@ -230,8 +234,8 @@ namespace Microsoft.PowerToys.Run.Plugin.Calculator.UnitTests
|
|||||||
var engine = new CalculateEngine();
|
var engine = new CalculateEngine();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
// Using InvariantCulture since this is internal
|
// Using en-us culture to have a fixed number style
|
||||||
var result = engine.Interpret(input, CultureInfo.InvariantCulture, out _);
|
var result = engine.Interpret(input, new CultureInfo("en-us"), out _);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.IsNotNull(result);
|
Assert.IsNotNull(result);
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ namespace Microsoft.PowerToys.Run.Plugin.Calculator.UnitTests
|
|||||||
[DataRow("=2^96", "Result value was either too large or too small for a decimal number")]
|
[DataRow("=2^96", "Result value was either too large or too small for a decimal number")]
|
||||||
[DataRow("=+()", "Calculation result is not a valid number (NaN)")]
|
[DataRow("=+()", "Calculation result is not a valid number (NaN)")]
|
||||||
[DataRow("=[10,10]", "Unsupported use of square brackets")]
|
[DataRow("=[10,10]", "Unsupported use of square brackets")]
|
||||||
|
[DataRow("=5/0", "Expression contains division by zero")]
|
||||||
|
[DataRow("=5 / 0", "Expression contains division by zero")]
|
||||||
|
[DataRow("10+(8*9)/0+7", "Expression contains division by zero")]
|
||||||
|
[DataRow("10+(8*9)/0*7", "Expression contains division by zero")]
|
||||||
public void ErrorResultOnInvalidKeywordQuery(string typedString, string expectedResult)
|
public void ErrorResultOnInvalidKeywordQuery(string typedString, string expectedResult)
|
||||||
{
|
{
|
||||||
// Setup
|
// Setup
|
||||||
@@ -45,6 +49,10 @@ namespace Microsoft.PowerToys.Run.Plugin.Calculator.UnitTests
|
|||||||
[DataRow("2^96")]
|
[DataRow("2^96")]
|
||||||
[DataRow("+()")]
|
[DataRow("+()")]
|
||||||
[DataRow("[10,10]")]
|
[DataRow("[10,10]")]
|
||||||
|
[DataRow("5/0")]
|
||||||
|
[DataRow("5 / 0")]
|
||||||
|
[DataRow("10+(8*9)/0+7")]
|
||||||
|
[DataRow("10+(8*9)/0*7")]
|
||||||
public void NoResultOnInvalidGlobalQuery(string typedString)
|
public void NoResultOnInvalidGlobalQuery(string typedString)
|
||||||
{
|
{
|
||||||
// Setup
|
// Setup
|
||||||
@@ -57,5 +65,53 @@ namespace Microsoft.PowerToys.Run.Plugin.Calculator.UnitTests
|
|||||||
// Assert
|
// Assert
|
||||||
Assert.AreEqual(result, 0);
|
Assert.AreEqual(result, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[DataTestMethod]
|
||||||
|
[DataRow("9+")]
|
||||||
|
[DataRow("9-")]
|
||||||
|
[DataRow("9*")]
|
||||||
|
[DataRow("9|")]
|
||||||
|
[DataRow("9\\")]
|
||||||
|
[DataRow("9^")]
|
||||||
|
[DataRow("9=")]
|
||||||
|
[DataRow("9&")]
|
||||||
|
[DataRow("9/")]
|
||||||
|
[DataRow("9%")]
|
||||||
|
public void NoResultIfQueryEndsWithBinaryOperator(string typedString)
|
||||||
|
{
|
||||||
|
// Setup
|
||||||
|
Mock<Main> main = new ();
|
||||||
|
Query expectedQuery = new (typedString);
|
||||||
|
Query expectedQueryWithKeyword = new ("=" + typedString, "=");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = main.Object.Query(expectedQuery).Count;
|
||||||
|
var resultWithKeyword = main.Object.Query(expectedQueryWithKeyword).Count;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.AreEqual(result, 0);
|
||||||
|
Assert.AreEqual(resultWithKeyword, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataTestMethod]
|
||||||
|
[DataRow("10+(8*9)/0,5")] // German decimal digit separator
|
||||||
|
[DataRow("10+(8*9)/0.5")]
|
||||||
|
[DataRow("10+(8*9)/1,5")] // German decimal digit separator
|
||||||
|
[DataRow("10+(8*9)/1.5")]
|
||||||
|
public void NoErrorForDivisionByNumberWithDecimalDigits(string typedString)
|
||||||
|
{
|
||||||
|
// Setup
|
||||||
|
Mock<Main> main = new ();
|
||||||
|
Query expectedQuery = new (typedString);
|
||||||
|
Query expectedQueryWithKeyword = new ("=" + typedString, "=");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = main.Object.Query(expectedQuery).FirstOrDefault().SubTitle;
|
||||||
|
var resultWithKeyword = main.Object.Query(expectedQueryWithKeyword).FirstOrDefault().SubTitle;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.AreEqual(result, "Copy this number to the clipboard");
|
||||||
|
Assert.AreEqual(resultWithKeyword, "Copy this number to the clipboard");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using Mages.Core;
|
using Mages.Core;
|
||||||
|
|
||||||
namespace Microsoft.PowerToys.Run.Plugin.Calculator
|
namespace Microsoft.PowerToys.Run.Plugin.Calculator
|
||||||
@@ -34,6 +35,14 @@ namespace Microsoft.PowerToys.Run.Plugin.Calculator
|
|||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check for division by zero
|
||||||
|
// We check if the string contains a slash followed by space (optional) and zero. Whereas the zero must not followed by dot or comma as this indicates a number with decimal digits.
|
||||||
|
if (new Regex("\\/\\s*0(?![,\\.])").Match(input).Success)
|
||||||
|
{
|
||||||
|
error = Properties.Resources.wox_plugin_calculator_division_by_zero;
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
// mages has quirky log representation
|
// mages has quirky log representation
|
||||||
// mage has log == ln vs log10
|
// mage has log == ln vs log10
|
||||||
input = input.
|
input = input.
|
||||||
|
|||||||
@@ -38,9 +38,9 @@ namespace Microsoft.PowerToys.Run.Plugin.Calculator
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the input ends with a binary operator then it is not a valid input to mages and the Interpret function would throw an exception.
|
// If the input ends with a binary operator then it is not a valid input to mages and the Interpret function would throw an exception. Because we expect here that the user has not finished typing we block those inputs.
|
||||||
string trimmedInput = input.TrimEnd();
|
string trimmedInput = input.TrimEnd();
|
||||||
if (trimmedInput.EndsWith('+') || trimmedInput.EndsWith('-') || trimmedInput.EndsWith('*') || trimmedInput.EndsWith('|') || trimmedInput.EndsWith('\\') || trimmedInput.EndsWith('^') || trimmedInput.EndsWith('=') || trimmedInput.EndsWith('&'))
|
if (trimmedInput.EndsWith('+') || trimmedInput.EndsWith('-') || trimmedInput.EndsWith('*') || trimmedInput.EndsWith('|') || trimmedInput.EndsWith('\\') || trimmedInput.EndsWith('^') || trimmedInput.EndsWith('=') || trimmedInput.EndsWith('&') || trimmedInput.EndsWith('/') || trimmedInput.EndsWith('%'))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,6 +87,15 @@ namespace Microsoft.PowerToys.Run.Plugin.Calculator.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Expression contains division by zero.
|
||||||
|
/// </summary>
|
||||||
|
public static string wox_plugin_calculator_division_by_zero {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("wox_plugin_calculator_division_by_zero", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Unsupported use of square brackets.
|
/// Looks up a localized string similar to Unsupported use of square brackets.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -158,4 +158,7 @@
|
|||||||
<value>Ignores your system setting and returns numbers in the format '{0}'.</value>
|
<value>Ignores your system setting and returns numbers in the format '{0}'.</value>
|
||||||
<comment>{0} is a placeholder and will be replaced in code.</comment>
|
<comment>{0} is a placeholder and will be replaced in code.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="wox_plugin_calculator_division_by_zero" xml:space="preserve">
|
||||||
|
<value>Expression contains division by zero</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
Reference in New Issue
Block a user