mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-31 09:27:03 +01:00
Compare commits
3 Commits
jay/DarkMo
...
leilzh/cal
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9b966f20f | ||
|
|
eea81830f6 | ||
|
|
8569725e35 |
@@ -759,6 +759,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdvancedPaste-UITests", "sr
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{9B3962F4-AB69-4C2A-8917-2C8448AC6960}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.Calc.UnitTests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.Ext.Calc.UnitTests\Microsoft.CmdPal.Ext.Calc.UnitTests.csproj", "{E816D7AC-4688-4ECB-97CC-3D8E798F3825}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
@@ -2829,6 +2831,14 @@ Global
|
||||
{2B1505FA-132A-460B-B22B-7CC3FFAB0C5D}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{2B1505FA-132A-460B-B22B-7CC3FFAB0C5D}.Release|x64.ActiveCfg = Release|x64
|
||||
{2B1505FA-132A-460B-B22B-7CC3FFAB0C5D}.Release|x64.Build.0 = Release|x64
|
||||
{E816D7AC-4688-4ECB-97CC-3D8E798F3825}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{E816D7AC-4688-4ECB-97CC-3D8E798F3825}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{E816D7AC-4688-4ECB-97CC-3D8E798F3825}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{E816D7AC-4688-4ECB-97CC-3D8E798F3825}.Debug|x64.Build.0 = Debug|x64
|
||||
{E816D7AC-4688-4ECB-97CC-3D8E798F3825}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{E816D7AC-4688-4ECB-97CC-3D8E798F3825}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{E816D7AC-4688-4ECB-97CC-3D8E798F3825}.Release|x64.ActiveCfg = Release|x64
|
||||
{E816D7AC-4688-4ECB-97CC-3D8E798F3825}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -3127,6 +3137,7 @@ Global
|
||||
{E4BAAD93-A499-42FD-A741-7E9591594B61} = {1D78B84B-CA39-406C-98F4-71F7EC266CC0}
|
||||
{2B1505FA-132A-460B-B22B-7CC3FFAB0C5D} = {9B3962F4-AB69-4C2A-8917-2C8448AC6960}
|
||||
{9B3962F4-AB69-4C2A-8917-2C8448AC6960} = {9873BA05-4C41-4819-9283-CF45D795431B}
|
||||
{E816D7AC-4688-4ECB-97CC-3D8E798F3825} = {15EA681E-C7D8-13C7-8484-4AC65E1B71E8}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.CmdPal.Ext.Calc.Helper;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Calc.UnitTests;
|
||||
|
||||
[TestClass]
|
||||
public class BracketHelperTests
|
||||
{
|
||||
[DataTestMethod]
|
||||
[DataRow(null)]
|
||||
[DataRow("")]
|
||||
[DataRow("\t \r\n")]
|
||||
[DataRow("none")]
|
||||
[DataRow("()")]
|
||||
[DataRow("(())")]
|
||||
[DataRow("()()")]
|
||||
[DataRow("(()())")]
|
||||
[DataRow("([][])")]
|
||||
[DataRow("([(()[])[](([]()))])")]
|
||||
public void IsBracketComplete_TestValid_WhenCalled(string input)
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
var result = BracketHelper.IsBracketComplete(input);
|
||||
|
||||
// Assert
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("((((", "only opening brackets")]
|
||||
[DataRow("]]]", "only closing brackets")]
|
||||
[DataRow("([)(])", "inner bracket mismatch")]
|
||||
[DataRow(")(", "opening and closing reversed")]
|
||||
[DataRow("(]", "mismatch in bracket type")]
|
||||
public void IsBracketComplete_TestInvalid_WhenCalled(string input, string invalidReason)
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
var result = BracketHelper.IsBracketComplete(input);
|
||||
|
||||
// Assert
|
||||
Assert.IsFalse(result, invalidReason);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,389 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Microsoft.CmdPal.Ext.Calc.Helper;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Calc.UnitTests;
|
||||
|
||||
[TestClass]
|
||||
public class ExtendedCalculatorParserTests
|
||||
{
|
||||
[DataTestMethod]
|
||||
[DataRow(null)]
|
||||
[DataRow("")]
|
||||
[DataRow(" ")]
|
||||
public void InputValid_ThrowError_WhenCalledNullOrEmpty(string input)
|
||||
{
|
||||
// Act
|
||||
Assert.IsTrue(!CalculateHelper.InputValid(input));
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("test")]
|
||||
[DataRow("[10,10]")] // '[10,10]' is interpreted as array by mages engine
|
||||
public void Interpret_NoResult_WhenCalled(string input)
|
||||
{
|
||||
var settings = new SettingsManager();
|
||||
|
||||
var result = CalculateEngine.Interpret(settings, input, CultureInfo.CurrentCulture, out _);
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(default(CalculateResult), result);
|
||||
}
|
||||
|
||||
private static IEnumerable<object[]> Interpret_NoErrors_WhenCalledWithRounding_Data =>
|
||||
[
|
||||
["2 * 2", 4M],
|
||||
["-2 ^ 2", -4M],
|
||||
["-(2 ^ 2)", -4M],
|
||||
["2 * pi", 6.28318530717959M],
|
||||
["round(2 * pi)", 6M],
|
||||
|
||||
// ["1 == 2", default(decimal)],
|
||||
["pi * ( sin ( cos ( 2)))", -1.26995475603563M],
|
||||
["5.6/2", 2.8M],
|
||||
["123 * 4.56", 560.88M],
|
||||
["1 - 9.0 / 10", 0.1M],
|
||||
["0.5 * ((2*-395.2)+198.2)", -296.1M],
|
||||
["2+2.11", 4.11M],
|
||||
["8.43 + 4.43 - 12.86", 0M],
|
||||
["8.43 + 4.43 - 12.8", 0.06M],
|
||||
["exp(5)", 148.413159102577M],
|
||||
["e^5", 148.413159102577M],
|
||||
["e*2", 5.43656365691809M],
|
||||
["ln(3)", 1.09861228866811M],
|
||||
["log(3)", 0.47712125471966M],
|
||||
["log2(3)", 1.58496250072116M],
|
||||
["log10(3)", 0.47712125471966M],
|
||||
["ln(e)", 1M],
|
||||
["cosh(0)", 1M],
|
||||
];
|
||||
|
||||
[DataTestMethod]
|
||||
[DynamicData(nameof(Interpret_NoErrors_WhenCalledWithRounding_Data))]
|
||||
public void Interpret_NoErrors_WhenCalledWithRounding(string input, decimal expectedResult)
|
||||
{
|
||||
var settings = new SettingsManager();
|
||||
|
||||
// Act
|
||||
// Using InvariantCulture since this is internal
|
||||
var result = CalculateEngine.Interpret(settings, input, CultureInfo.InvariantCulture, out _);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(CalculateEngine.FormatMax15Digits(expectedResult, new CultureInfo("en-US")), result.RoundedResult);
|
||||
}
|
||||
|
||||
private static IEnumerable<object[]> Interpret_GreaterPrecision_WhenCalled_Data =>
|
||||
[
|
||||
["0.100000000000000000000", 0.1M],
|
||||
["0.200000000000000000000000", 0.2M],
|
||||
];
|
||||
|
||||
[DynamicData(nameof(Interpret_GreaterPrecision_WhenCalled_Data))]
|
||||
[DataTestMethod]
|
||||
public void Interpret_GreaterPrecision_WhenCalled(string input, decimal expectedResult)
|
||||
{
|
||||
// Arrange
|
||||
var settings = new SettingsManager();
|
||||
|
||||
// Act
|
||||
// Using InvariantCulture since this is internal
|
||||
var result = CalculateEngine.Interpret(settings, input, CultureInfo.InvariantCulture, out _);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(expectedResult, result.Result);
|
||||
}
|
||||
|
||||
private static IEnumerable<object[]> Interpret_DifferentCulture_WhenCalled_Data =>
|
||||
[
|
||||
["4.5/3", 1.5M, "nl-NL"],
|
||||
["4.5/3", 1.5M, "en-EN"],
|
||||
["4.5/3", 1.5M, "de-DE"],
|
||||
];
|
||||
|
||||
[DataTestMethod]
|
||||
[DynamicData(nameof(Interpret_DifferentCulture_WhenCalled_Data))]
|
||||
public void Interpret_DifferentCulture_WhenCalled(string input, decimal expectedResult, string cultureName)
|
||||
{
|
||||
// Arrange
|
||||
var cultureInfo = CultureInfo.GetCultureInfo(cultureName);
|
||||
var settings = new SettingsManager();
|
||||
|
||||
// Act
|
||||
var result = CalculateEngine.Interpret(settings, input, cultureInfo, out _);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(CalculateEngine.Round(expectedResult), result.RoundedResult);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("log(3)", true)]
|
||||
[DataRow("ln(3)", true)]
|
||||
[DataRow("log2(3)", true)]
|
||||
[DataRow("log10(3)", true)]
|
||||
[DataRow("log2", false)]
|
||||
[DataRow("log10", false)]
|
||||
[DataRow("log", false)]
|
||||
[DataRow("ln", false)]
|
||||
[DataRow("ceil(2 * (pi ^ 2))", true)]
|
||||
[DataRow("((1 * 2)", false)]
|
||||
[DataRow("(1 * 2)))", false)]
|
||||
[DataRow("abcde", false)]
|
||||
[DataRow("1 + 2 +", false)]
|
||||
[DataRow("1+2*", false)]
|
||||
[DataRow("1+2/", false)]
|
||||
[DataRow("1+2%", false)]
|
||||
[DataRow("1 && 3 &&", false)]
|
||||
[DataRow("sqrt( 36)", true)]
|
||||
[DataRow("max 4", false)]
|
||||
[DataRow("sin(0)", true)]
|
||||
[DataRow("sinh(1)", true)]
|
||||
[DataRow("tanh(0)", true)]
|
||||
[DataRow("artanh(pi/2)", true)]
|
||||
[DataRow("cosh", false)]
|
||||
[DataRow("cos", false)]
|
||||
[DataRow("abs", false)]
|
||||
[DataRow("1+1.1e3", true)]
|
||||
[DataRow("randi(8)", true)]
|
||||
[DataRow("randi()", false)]
|
||||
[DataRow("randi(0.5)", true)]
|
||||
[DataRow("rand()", true)]
|
||||
[DataRow("rand(0.5)", false)]
|
||||
[DataRow("0X78AD+0o123", true)]
|
||||
[DataRow("0o9", false)]
|
||||
public void InputValid_TestValid_WhenCalled(string input, bool valid)
|
||||
{
|
||||
// Act
|
||||
var result = CalculateHelper.InputValid(input);
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(valid, result);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("1-1")]
|
||||
[DataRow("sin(0)")]
|
||||
[DataRow("sinh(0)")]
|
||||
public void Interpret_MustReturnResult_WhenResultIsZero(string input)
|
||||
{
|
||||
// Arrange
|
||||
var settings = new SettingsManager();
|
||||
|
||||
// Act
|
||||
// Using InvariantCulture since this is internal
|
||||
var result = CalculateEngine.Interpret(settings, input, CultureInfo.InvariantCulture, out _);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(0.0M, result.Result);
|
||||
}
|
||||
|
||||
private static IEnumerable<object[]> Interpret_MustReturnExpectedResult_WhenCalled_Data =>
|
||||
[
|
||||
|
||||
// ["factorial(5)", 120M], ToDo: this don't support now
|
||||
// ["sign(-2)", -1M],
|
||||
// ["sign(2)", +1M],
|
||||
["abs(-2)", 2M],
|
||||
["abs(2)", 2M],
|
||||
["0+(1*2)/(0+1)", 2M], // Validate that division by "(0+1)" is not interpret as division by zero.
|
||||
["0+(1*2)/0.5", 4M], // Validate that division by number with decimal digits is not interpret as division by zero.
|
||||
];
|
||||
|
||||
[DataTestMethod]
|
||||
[DynamicData(nameof(Interpret_MustReturnExpectedResult_WhenCalled_Data))]
|
||||
public void Interpret_MustReturnExpectedResult_WhenCalled(string input, decimal expectedResult)
|
||||
{
|
||||
// Arrange
|
||||
var settings = new SettingsManager();
|
||||
|
||||
// Act
|
||||
// Using en-us culture to have a fixed number style
|
||||
var result = CalculateEngine.Interpret(settings, input, new CultureInfo("en-us", false), out _);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(expectedResult, result.Result);
|
||||
}
|
||||
|
||||
private static IEnumerable<object[]> Interpret_TestScientificNotation_WhenCalled_Data =>
|
||||
[
|
||||
["0.2E1", "en-US", 2M],
|
||||
["0,2E1", "pt-PT", 2M],
|
||||
];
|
||||
|
||||
[DataTestMethod]
|
||||
[DynamicData(nameof(Interpret_TestScientificNotation_WhenCalled_Data))]
|
||||
public void Interpret_TestScientificNotation_WhenCalled(string input, string sourceCultureName, decimal expectedResult)
|
||||
{
|
||||
// Arrange
|
||||
var translator = NumberTranslator.Create(new CultureInfo(sourceCultureName, false), new CultureInfo("en-US", false));
|
||||
var settings = new SettingsManager();
|
||||
|
||||
// Act
|
||||
// Using en-us culture to have a fixed number style
|
||||
var translatedInput = translator.Translate(input);
|
||||
var result = CalculateEngine.Interpret(settings, translatedInput, new CultureInfo("en-US", false), out _);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(expectedResult, result.Result);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("sin(90)", "sin((pi / 180) * (90))")]
|
||||
[DataRow("arcsin(0.5)", "(180 / pi) * (arcsin(0.5))")]
|
||||
[DataRow("sin(sin(30))", "sin((pi / 180) * (sin((pi / 180) * (30))))")]
|
||||
[DataRow("cos(tan(45))", "cos((pi / 180) * (tan((pi / 180) * (45))))")]
|
||||
[DataRow("arctan(sin(30))", "(180 / pi) * (arctan(sin((pi / 180) * (30))))")]
|
||||
[DataRow("sin(cos(tan(30)))", "sin((pi / 180) * (cos((pi / 180) * (tan((pi / 180) * (30))))))")]
|
||||
[DataRow("sin(arcsin(0.5))", "sin((pi / 180) * ((180 / pi) * (arcsin(0.5))))")]
|
||||
[DataRow("sin(30) + cos(60)", "sin((pi / 180) * (30)) + cos((pi / 180) * (60))")]
|
||||
[DataRow("sin(30 + 15)", "sin((pi / 180) * (30 + 15))")]
|
||||
[DataRow("sin(45) * cos(45) - tan(30)", "sin((pi / 180) * (45)) * cos((pi / 180) * (45)) - tan((pi / 180) * (30))")]
|
||||
[DataRow("arcsin(arccos(0.5))", "(180 / pi) * (arcsin((180 / pi) * (arccos(0.5))))")]
|
||||
[DataRow("sin(sin(sin(30)))", "sin((pi / 180) * (sin((pi / 180) * (sin((pi / 180) * (30))))))")]
|
||||
[DataRow("log(10)", "log(10)")]
|
||||
[DataRow("sin(30) + pi", "sin((pi / 180) * (30)) + pi")]
|
||||
[DataRow("sin(-30)", "sin((pi / 180) * (-30))")]
|
||||
[DataRow("sin((30))", "sin((pi / 180) * ((30)))")]
|
||||
[DataRow("arcsin(1) * 2", "(180 / pi) * (arcsin(1)) * 2")]
|
||||
[DataRow("cos(1/2)", "cos((pi / 180) * (1/2))")]
|
||||
[DataRow("sin ( 90 )", "sin ((pi / 180) * ( 90 ))")]
|
||||
[DataRow("cos(arcsin(sin(45)))", "cos((pi / 180) * ((180 / pi) * (arcsin(sin((pi / 180) * (45))))))")]
|
||||
public void UpdateTrigFunctions_Degrees(string input, string expectedResult)
|
||||
{
|
||||
// Call UpdateTrigFunctions in degrees mode
|
||||
var result = CalculateHelper.UpdateTrigFunctions(input, CalculateEngine.TrigMode.Degrees);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(expectedResult, result);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("sin(90)", "sin((pi / 200) * (90))")]
|
||||
[DataRow("arcsin(0.5)", "(200 / pi) * (arcsin(0.5))")]
|
||||
[DataRow("sin(sin(30))", "sin((pi / 200) * (sin((pi / 200) * (30))))")]
|
||||
[DataRow("cos(tan(45))", "cos((pi / 200) * (tan((pi / 200) * (45))))")]
|
||||
[DataRow("arctan(sin(30))", "(200 / pi) * (arctan(sin((pi / 200) * (30))))")]
|
||||
[DataRow("sin(cos(tan(30)))", "sin((pi / 200) * (cos((pi / 200) * (tan((pi / 200) * (30))))))")]
|
||||
[DataRow("sin(arcsin(0.5))", "sin((pi / 200) * ((200 / pi) * (arcsin(0.5))))")]
|
||||
[DataRow("sin(30) + cos(60)", "sin((pi / 200) * (30)) + cos((pi / 200) * (60))")]
|
||||
[DataRow("sin(30 + 15)", "sin((pi / 200) * (30 + 15))")]
|
||||
[DataRow("sin(45) * cos(45) - tan(30)", "sin((pi / 200) * (45)) * cos((pi / 200) * (45)) - tan((pi / 200) * (30))")]
|
||||
[DataRow("arcsin(arccos(0.5))", "(200 / pi) * (arcsin((200 / pi) * (arccos(0.5))))")]
|
||||
[DataRow("sin(sin(sin(30)))", "sin((pi / 200) * (sin((pi / 200) * (sin((pi / 200) * (30))))))")]
|
||||
[DataRow("log(10)", "log(10)")]
|
||||
[DataRow("sin(30) + pi", "sin((pi / 200) * (30)) + pi")]
|
||||
[DataRow("sin(-30)", "sin((pi / 200) * (-30))")]
|
||||
[DataRow("sin((30))", "sin((pi / 200) * ((30)))")]
|
||||
[DataRow("arcsin(1) * 2", "(200 / pi) * (arcsin(1)) * 2")]
|
||||
[DataRow("cos(1/2)", "cos((pi / 200) * (1/2))")]
|
||||
[DataRow("sin ( 90 )", "sin ((pi / 200) * ( 90 ))")]
|
||||
[DataRow("cos(arcsin(sin(45)))", "cos((pi / 200) * ((200 / pi) * (arcsin(sin((pi / 200) * (45))))))")]
|
||||
public void UpdateTrigFunctions_Gradians(string input, string expectedResult)
|
||||
{
|
||||
// Call UpdateTrigFunctions in gradians mode
|
||||
var result = CalculateHelper.UpdateTrigFunctions(input, CalculateEngine.TrigMode.Gradians);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(expectedResult, result);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("rad(30)", "(180 / pi) * (30)")]
|
||||
[DataRow("rad( 30 )", "(180 / pi) * ( 30 )")]
|
||||
[DataRow("deg(30)", "(30)")]
|
||||
[DataRow("grad(30)", "(9 / 10) * (30)")]
|
||||
[DataRow("rad( 30)", "(180 / pi) * ( 30)")]
|
||||
[DataRow("rad(30 )", "(180 / pi) * (30 )")]
|
||||
[DataRow("rad( 30 )", "(180 / pi) * ( 30 )")]
|
||||
[DataRow("rad(deg(30))", "(180 / pi) * ((30))")]
|
||||
[DataRow("deg(rad(30))", "((180 / pi) * (30))")]
|
||||
[DataRow("grad(rad(30))", "(9 / 10) * ((180 / pi) * (30))")]
|
||||
[DataRow("rad(grad(30))", "(180 / pi) * ((9 / 10) * (30))")]
|
||||
[DataRow("rad(30) + deg(45)", "(180 / pi) * (30) + (45)")]
|
||||
[DataRow("sin(rad(30))", "sin((180 / pi) * (30))")]
|
||||
[DataRow("cos( rad( 45 ) )", "cos( (180 / pi) * ( 45 ) )")]
|
||||
[DataRow("tan(rad(grad(90)))", "tan((180 / pi) * ((9 / 10) * (90)))")]
|
||||
[DataRow("rad(30) + rad(45)", "(180 / pi) * (30) + (180 / pi) * (45)")]
|
||||
[DataRow("rad(30) * grad(90)", "(180 / pi) * (30) * (9 / 10) * (90)")]
|
||||
[DataRow("rad(30)/rad(45)", "(180 / pi) * (30)/(180 / pi) * (45)")]
|
||||
public void ExpandTrigConversions_Degrees(string input, string expectedResult)
|
||||
{
|
||||
// Call ExpandTrigConversions in degrees mode
|
||||
var result = CalculateHelper.ExpandTrigConversions(input, CalculateEngine.TrigMode.Degrees);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(expectedResult, result);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("rad(30)", "(30)")]
|
||||
[DataRow("rad( 30 )", "( 30 )")]
|
||||
[DataRow("deg(30)", "(pi / 180) * (30)")]
|
||||
[DataRow("grad(30)", "(pi / 200) * (30)")]
|
||||
[DataRow("rad( 30)", "( 30)")]
|
||||
[DataRow("rad(30 )", "(30 )")]
|
||||
[DataRow("rad( 30 )", "( 30 )")]
|
||||
[DataRow("rad(deg(30))", "((pi / 180) * (30))")]
|
||||
[DataRow("deg(rad(30))", "(pi / 180) * ((30))")]
|
||||
[DataRow("grad(rad(30))", "(pi / 200) * ((30))")]
|
||||
[DataRow("rad(grad(30))", "((pi / 200) * (30))")]
|
||||
[DataRow("rad(30) + deg(45)", "(30) + (pi / 180) * (45)")]
|
||||
[DataRow("sin(rad(30))", "sin((30))")]
|
||||
[DataRow("cos( rad( 45 ) )", "cos( ( 45 ) )")]
|
||||
[DataRow("tan(rad(grad(90)))", "tan(((pi / 200) * (90)))")]
|
||||
[DataRow("rad(30) + rad(45)", "(30) + (45)")]
|
||||
[DataRow("rad(30) * grad(90)", "(30) * (pi / 200) * (90)")]
|
||||
[DataRow("rad(30)/rad(45)", "(30)/(45)")]
|
||||
public void ExpandTrigConversions_Radians(string input, string expectedResult)
|
||||
{
|
||||
// Call ExpandTrigConversions in radians mode
|
||||
var result = CalculateHelper.ExpandTrigConversions(input, CalculateEngine.TrigMode.Radians);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(expectedResult, result);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("rad(30)", "(200 / pi) * (30)")]
|
||||
[DataRow("rad( 30 )", "(200 / pi) * ( 30 )")]
|
||||
[DataRow("deg(30)", "(10 / 9) * (30)")]
|
||||
[DataRow("grad(30)", "(30)")]
|
||||
[DataRow("rad( 30)", "(200 / pi) * ( 30)")]
|
||||
[DataRow("rad(30 )", "(200 / pi) * (30 )")]
|
||||
[DataRow("rad( 30 )", "(200 / pi) * ( 30 )")]
|
||||
[DataRow("rad(deg(30))", "(200 / pi) * ((10 / 9) * (30))")]
|
||||
[DataRow("deg(rad(30))", "(10 / 9) * ((200 / pi) * (30))")]
|
||||
[DataRow("grad(rad(30))", "((200 / pi) * (30))")]
|
||||
[DataRow("rad(grad(30))", "(200 / pi) * ((30))")]
|
||||
[DataRow("rad(30) + deg(45)", "(200 / pi) * (30) + (10 / 9) * (45)")]
|
||||
[DataRow("sin(rad(30))", "sin((200 / pi) * (30))")]
|
||||
[DataRow("cos( rad( 45 ) )", "cos( (200 / pi) * ( 45 ) )")]
|
||||
[DataRow("tan(rad(grad(90)))", "tan((200 / pi) * ((90)))")]
|
||||
[DataRow("rad(30) + rad(45)", "(200 / pi) * (30) + (200 / pi) * (45)")]
|
||||
[DataRow("rad(30) * grad(90)", "(200 / pi) * (30) * (90)")]
|
||||
[DataRow("rad(30)/rad(45)", "(200 / pi) * (30)/(200 / pi) * (45)")]
|
||||
public void ExpandTrigConversions_Gradians(string input, string expectedResult)
|
||||
{
|
||||
// Call ExpandTrigConversions in gradians mode
|
||||
var result = CalculateHelper.ExpandTrigConversions(input, CalculateEngine.TrigMode.Gradians);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(expectedResult, result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<!-- Look at Directory.Build.props in root for common stuff as well -->
|
||||
<Import Project="..\..\..\..\Common.Dotnet.CsWinRT.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<IsPackable>false</IsPackable>
|
||||
<RootNamespace>Microsoft.CmdPal.Ext.Calc.UnitTests</RootNamespace>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Moq" />
|
||||
<PackageReference Include="MSTest" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\ext\Microsoft.CmdPal.Ext.Calc\Microsoft.CmdPal.Ext.Calc.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,185 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Microsoft.CmdPal.Ext.Calc.Helper;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Calc.UnitTests;
|
||||
|
||||
[TestClass]
|
||||
public class NumberTranslatorTests
|
||||
{
|
||||
[DataTestMethod]
|
||||
[DataRow(null, "en-US")]
|
||||
[DataRow("de-DE", null)]
|
||||
public void Create_ThrowError_WhenCalledNullOrEmpty(string sourceCultureName, string targetCultureName)
|
||||
{
|
||||
// Arrange
|
||||
CultureInfo sourceCulture = sourceCultureName != null ? new CultureInfo(sourceCultureName) : null;
|
||||
CultureInfo targetCulture = targetCultureName != null ? new CultureInfo(targetCultureName) : null;
|
||||
|
||||
// Act
|
||||
Assert.ThrowsException<ArgumentNullException>(() => NumberTranslator.Create(sourceCulture, targetCulture));
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("en-US", "en-US")]
|
||||
[DataRow("en-EN", "en-US")]
|
||||
[DataRow("de-DE", "en-US")]
|
||||
public void Create_WhenCalled(string sourceCultureName, string targetCultureName)
|
||||
{
|
||||
// Arrange
|
||||
CultureInfo sourceCulture = new CultureInfo(sourceCultureName);
|
||||
CultureInfo targetCulture = new CultureInfo(targetCultureName);
|
||||
|
||||
// Act
|
||||
var translator = NumberTranslator.Create(sourceCulture, targetCulture);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(translator);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow(null)]
|
||||
public void Translate_ThrowError_WhenCalledNull(string input)
|
||||
{
|
||||
// Arrange
|
||||
var translator = NumberTranslator.Create(new CultureInfo("de-DE", false), new CultureInfo("en-US", false));
|
||||
|
||||
// Act
|
||||
Assert.ThrowsException<ArgumentNullException>(() => translator.Translate(input));
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("")]
|
||||
[DataRow(" ")]
|
||||
public void Translate_WhenCalledEmpty(string input)
|
||||
{
|
||||
// Arrange
|
||||
var translator = NumberTranslator.Create(new CultureInfo("de-DE", false), new CultureInfo("en-US", false));
|
||||
|
||||
// Act
|
||||
var result = translator.Translate(input);
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(input, result);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("2,0 * 2", "2.0 * 2")]
|
||||
[DataRow("4 * 3,6 + 9", "4 * 3.6 + 9")]
|
||||
[DataRow("5,2+6", "5.2+6")]
|
||||
[DataRow("round(2,5)", "round(2.5)")]
|
||||
[DataRow("3,3333", "3.3333")]
|
||||
[DataRow("max(2;3)", "max(2,3)")]
|
||||
public void Translate_NoErrors_WhenCalled(string input, string expectedResult)
|
||||
{
|
||||
// Arrange
|
||||
var translator = NumberTranslator.Create(new CultureInfo("de-DE", false), new CultureInfo("en-US", false));
|
||||
|
||||
// Act
|
||||
var result = translator.Translate(input);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(expectedResult, result);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("2.0 * 2", "2,0 * 2")]
|
||||
[DataRow("4 * 3.6 + 9", "4 * 3,6 + 9")]
|
||||
[DataRow("5.2+6", "5,2+6")]
|
||||
[DataRow("round(2.5)", "round(2,5)")]
|
||||
[DataRow("3.3333", "3,3333")]
|
||||
public void TranslateBack_NoErrors_WhenCalled(string input, string expectedResult)
|
||||
{
|
||||
// Arrange
|
||||
var translator = NumberTranslator.Create(new CultureInfo("de-DE", false), new CultureInfo("en-US", false));
|
||||
|
||||
// Act
|
||||
var result = translator.TranslateBack(input);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(expectedResult, result);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow(".", ",", "2,000,000", "2000000")]
|
||||
[DataRow(".", ",", "2,000,000.6", "2000000.6")]
|
||||
[DataRow(",", ".", "2.000.000", "2000000")]
|
||||
[DataRow(",", ".", "2.000.000,6", "2000000.6")]
|
||||
public void Translate_RemoveNumberGroupSeparator_WhenCalled(string decimalSeparator, string groupSeparator, string input, string expectedResult)
|
||||
{
|
||||
// Arrange
|
||||
var sourceCulture = new CultureInfo("en-US", false)
|
||||
{
|
||||
NumberFormat =
|
||||
{
|
||||
NumberDecimalSeparator = decimalSeparator,
|
||||
NumberGroupSeparator = groupSeparator,
|
||||
},
|
||||
};
|
||||
var translator = NumberTranslator.Create(sourceCulture, new CultureInfo("en-US", false));
|
||||
|
||||
// Act
|
||||
var result = translator.Translate(input);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(expectedResult, result);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("de-DE", "12,0004", "12.0004")]
|
||||
[DataRow("de-DE", "0xF000", "61440")]
|
||||
[DataRow("de-DE", "0", "0")]
|
||||
[DataRow("de-DE", "00", "0")]
|
||||
[DataRow("de-DE", "12.004", "12004")] // . is the group separator in de-DE
|
||||
[DataRow("de-DE", "12.04", "1204")]
|
||||
[DataRow("de-DE", "12.4", "124")]
|
||||
[DataRow("de-DE", "3.004.044.444,05", "3004044444.05")]
|
||||
[DataRow("de-DE", "123.01 + 52.30", "12301 + 5230")]
|
||||
[DataRow("de-DE", "123.001 + 52.30", "123001 + 5230")]
|
||||
[DataRow("fr-FR", "0", "0")]
|
||||
[DataRow("fr-FR", "00", "0")]
|
||||
[DataRow("fr-FR", "12.004", "12.004")] // . is not decimal or group separator in fr-FR
|
||||
[DataRow("fr-FR", "12.04", "12.04")]
|
||||
[DataRow("fr-FR", "12.4", "12.4")]
|
||||
[DataRow("fr-FR", "12.0004", "12.0004")]
|
||||
|
||||
// [DataRow("fr-FR", "123.01 + 52.30", "123.01 + 52.30")]
|
||||
// [DataRow("fr-FR", "123.001 + 52.30", "123.001 + 52.30")] passed locally, failed in CI
|
||||
public void Translate_NoRemovalOfLeadingZeroesOnEdgeCases(string sourceCultureName, string input, string expectedResult)
|
||||
{
|
||||
// Arrange
|
||||
var translator = NumberTranslator.Create(new CultureInfo(sourceCultureName, false), new CultureInfo("en-US", false));
|
||||
|
||||
// Act
|
||||
var result = translator.Translate(input);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(expectedResult, result);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("en-US", "0xF000", "61440")]
|
||||
[DataRow("en-US", "0xf4572220", "4099351072")]
|
||||
[DataRow("en-US", "0x12345678", "305419896")]
|
||||
public void Translate_LargeHexadecimalNumbersToDecimal(string sourceCultureName, string input, string expectedResult)
|
||||
{
|
||||
// Arrange
|
||||
var translator = NumberTranslator.Create(new CultureInfo(sourceCultureName, false), new CultureInfo("en-US", false));
|
||||
|
||||
// Act
|
||||
var result = translator.Translate(input);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(expectedResult, result);
|
||||
}
|
||||
}
|
||||
@@ -108,7 +108,7 @@ public static class CalculateEngine
|
||||
/// 100000.9999999999 → "100001"
|
||||
/// 1234567890123.45 → "1234567890123.45"
|
||||
/// </summary>
|
||||
private static decimal FormatMax15Digits(decimal value, CultureInfo cultureInfo)
|
||||
public static decimal FormatMax15Digits(decimal value, CultureInfo cultureInfo)
|
||||
{
|
||||
var absValue = Math.Abs(value);
|
||||
var integerDigits = absValue >= 1 ? (int)Math.Floor(Math.Log10((double)absValue)) + 1 : 1;
|
||||
|
||||
Reference in New Issue
Block a user