Hello GitHub
131
internal/Calculator.TestPackage/Calculator.TestPackage.csproj
Normal file
@@ -0,0 +1,131 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{24767C43-CD5A-4DC9-8D6B-429F255524E5}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Calculator.TestPackage</RootNamespace>
|
||||
<AssemblyName>Calculator.TestPackage</AssemblyName>
|
||||
<TargetFrameworkIdentifier>.NETPortable</TargetFrameworkIdentifier>
|
||||
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
|
||||
<NuGetTargetMoniker>.NETCore,Version=v5.0</NuGetTargetMoniker>
|
||||
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
||||
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.17763.0</TargetPlatformVersion>
|
||||
<TargetPlatformMinVersion>10.0.17134.0</TargetPlatformMinVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<!-- The app doesn't contain any tests so we don't generate a testmd -->
|
||||
<NoTestMD>true</NoTestMD>
|
||||
<NoPackage Condition="'$(IsTFSBuild)' != 'True'">True</NoPackage>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\x86</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\x86</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\x64</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\x64</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|ARM' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\arm</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>ARM</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|ARM' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\arm</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>ARM</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|ARM64' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\ARM64\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>ARM64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|ARM64' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\ARM64\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>ARM64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Calculator.TestPackage.wm.xml" />
|
||||
<None Include="project.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Calculator\Calculator.vcxproj">
|
||||
<Project>{9447424a-0e05-4911-beb8-e0354405f39a}</Project>
|
||||
<Name>Calculator</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '15.0' ">
|
||||
<VisualStudioVersion>15.0</VisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<!-- Redefine build target as we don't want to build anything. -->
|
||||
<Target Name="Build" />
|
||||
<Target Name="Clean" />
|
||||
<Target Name="Rebuild" />
|
||||
<!-- Append the appx properties to the custom macros as we use this in the testmd.definition file. -->
|
||||
<Target Name="AppendUniversalTestCustomMacros" BeforeTargets="BuildUniversalTest">
|
||||
<ItemGroup>
|
||||
<AppxBundleOutput Include="$(OutDir)..\Calculator\AppPackages\**\*.appxbundle" />
|
||||
<AppxPackagePublicKeyFile Include="$(OutDir)..\Calculator\AppPackages\**\*.cer" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<AppxPackageTestDir>@(AppxBundleOutput->'%(RootDir)%(Directory)')</AppxPackageTestDir>
|
||||
<UniversalTestCustomMacros Condition="'$(Configuration)'=='Debug'">$(UniversalTestCustomMacros)AppxPackageVCLibsDependency=$(AppxPackageTestDir)Dependencies\$(PlatformTarget)\Microsoft.VCLibs.$(PlatformTarget).Debug.14.00.appx;</UniversalTestCustomMacros>
|
||||
<UniversalTestCustomMacros Condition="'$(Configuration)'=='Release'">$(UniversalTestCustomMacros)AppxPackageVCLibsDependency=$(AppxPackageTestDir)Dependencies\$(PlatformTarget)\Microsoft.VCLibs.$(PlatformTarget).14.00.appx;</UniversalTestCustomMacros>
|
||||
<UniversalTestCustomMacros>$(UniversalTestCustomMacros)AppxPackageWinUIDependency=$(AppxPackageTestDir)Dependencies\$(PlatformTarget)\Microsoft.UI.Xaml.2.0.appx;</UniversalTestCustomMacros>
|
||||
<UniversalTestCustomMacros>$(UniversalTestCustomMacros)AppxPackagePublicKeyFile=@(AppxPackagePublicKeyFile->'%(FullPath)');AppxBundleOutput=@(AppxBundleOutput->'%(FullPath)');</UniversalTestCustomMacros>
|
||||
</PropertyGroup>
|
||||
</Target>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Copyright (c) Microsoft Corporation. All rights reserved.-->
|
||||
<identity
|
||||
xmlns="urn:Microsoft.CompPlat/ManifestSchema.v1.00"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
name="App"
|
||||
namespace="Calculator"
|
||||
owner="Microsoft">
|
||||
<files>
|
||||
<file
|
||||
source="$(AppxBundleOutput)"
|
||||
destinationDir="$(runtime.testbin)"
|
||||
name="Calculator.appxbundle" />
|
||||
<file
|
||||
source="$(AppxPackagePublicKeyFile)"
|
||||
destinationDir="$(runtime.testbin)"
|
||||
name="Calculator.cer" />
|
||||
<file
|
||||
source="$(AppxPackageVCLibsDependency)"
|
||||
destinationDir="$(runtime.testbin)"
|
||||
name="Microsoft.VCLibs.appx" />
|
||||
<file
|
||||
source="$(AppxPackageWinUIDependency)"
|
||||
destinationDir="$(runtime.testbin)"
|
||||
name="Microsoft.UI.Xaml.appx" />
|
||||
</files>
|
||||
</identity>
|
13
internal/Calculator.TestPackage/project.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"Microsoft.TestInfrastructure.UniversalTest": "1.0.20181107.1"
|
||||
},
|
||||
"frameworks": {
|
||||
"netcore50": {}
|
||||
},
|
||||
"runtimes": {
|
||||
"win10-arm": {},
|
||||
"win10-x64": {},
|
||||
"win10-x86": {}
|
||||
}
|
||||
}
|
@@ -0,0 +1,99 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{A43517B5-8BE3-4312-913F-004978C34444}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Calculator.UIAutomationLibrary</RootNamespace>
|
||||
<AssemblyName>Calculator.UIAutomationLibrary</AssemblyName>
|
||||
<TargetFrameworkIdentifier>.NETPortable</TargetFrameworkIdentifier>
|
||||
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
|
||||
<NuGetTargetMoniker>.NETCore,Version=v5.0</NuGetTargetMoniker>
|
||||
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
||||
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.17763.0</TargetPlatformVersion>
|
||||
<TargetPlatformMinVersion>10.0.17134.0</TargetPlatformMinVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<MinimumVisualStudioVersion>15.0</MinimumVisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CalculatorAppLauncher.cs" />
|
||||
<Compile Include="Components\App\CalculatorAppLfm.cs" />
|
||||
<Compile Include="Components\App\CalculatorAppPom.cs" />
|
||||
<Compile Include="Components\ContentDialogLfm.cs" />
|
||||
<Compile Include="Components\Pages\CalculatorBasePom.cs" />
|
||||
<Compile Include="Components\Pages\AboutFlyoutLfm.cs" />
|
||||
<Compile Include="Components\Pages\AboutFlyoutPom.cs" />
|
||||
<Compile Include="Components\Pages\DateCalculatorLfm.cs" />
|
||||
<Compile Include="Components\Pages\DateCalculatorPom.cs" />
|
||||
<Compile Include="Components\Pages\UnitConverterLfm.cs" />
|
||||
<Compile Include="Components\Pages\UnitConverterPom.cs" />
|
||||
<Compile Include="Components\Shared\HistoryLfm.cs" />
|
||||
<Compile Include="Components\Shared\HistoryPom.cs" />
|
||||
<Compile Include="Components\Shared\ICanFocusWithClicks.cs" />
|
||||
<Compile Include="Components\Shared\MemoryLfm.cs" />
|
||||
<Compile Include="Components\Shared\MemoryPom.cs" />
|
||||
<Compile Include="Components\Pages\NavBarLfm.cs" />
|
||||
<Compile Include="Components\Pages\NavBarPom.cs" />
|
||||
<Compile Include="Components\Shared\NumberPadPom.cs" />
|
||||
<Compile Include="Components\Pages\ProgrammerCalculatorLfm.cs" />
|
||||
<Compile Include="Components\Pages\ProgrammerCalculatorPom.cs" />
|
||||
<Compile Include="Components\Pages\ScientificCalculatorLfm.cs" />
|
||||
<Compile Include="Components\Pages\ScientificCalculatorPom.cs" />
|
||||
<Compile Include="Components\Pages\StandardCalculatorLfm.cs" />
|
||||
<Compile Include="Components\Pages\StandardCalculatorPom.cs" />
|
||||
<Compile Include="Components\Pages\MainPageLfm.cs" />
|
||||
<Compile Include="Components\Pages\MainPagePom.cs" />
|
||||
<Compile Include="Utilities\Impersonator.cs" />
|
||||
<Compile Include="Utilities\PerfTestConstants.cs" />
|
||||
<Compile Include="Tests\BasicCalculationTest.cs" />
|
||||
<Compile Include="Tests\ScientificCalculationTest.cs" />
|
||||
<Compile Include="Utilities\EtwHelper.cs" />
|
||||
<Compile Include="Utilities\InstallHelper.cs" />
|
||||
<Compile Include="Components\ContentDialogPom.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Utilities\Constants.cs" />
|
||||
<Compile Include="Utilities\NativeMethods.cs" />
|
||||
<Compile Include="Utilities\ServiceHelper.cs" />
|
||||
<Compile Include="Utilities\UIObjectExtensions.cs" />
|
||||
<Compile Include="Utilities\Utilities.cs" />
|
||||
<Compile Include="Utilities\WindowHelper.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="project.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '15.0' ">
|
||||
<VisualStudioVersion>15.0</VisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
|
||||
<!--additional imports-->
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
@@ -0,0 +1,63 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Etw.Managed;
|
||||
using Microsoft.OneCoreUap.Test.AppModel;
|
||||
using MS.Internal.Mita.Foundation;
|
||||
using MS.Internal.Mita.Foundation.Controls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Calculator.UIAutomationLibrary.Components;
|
||||
using WEX.Logging.Interop;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary
|
||||
{
|
||||
/// <summary>
|
||||
/// Class that can open and close the Calculator app.
|
||||
/// </summary>
|
||||
public static class CalculatorAppLauncher
|
||||
{
|
||||
public const string CoreWindowClassName = "Windows.UI.Core.CoreWindow";
|
||||
|
||||
// This doesn't actually work right now becaue popup will disappear
|
||||
// Bug 13713223: ContentDialog/Popup does not show up in the UIA tree when Windows.Current.Content has an AutomationName set.
|
||||
// public static readonly UICondition TopLevelWindowUICondition = UICondition.CreateFromId(Constants.TopLevelWindowAutomationId);
|
||||
public static readonly UICondition CoreWindowUICondition = UICondition.CreateFromClassName(CoreWindowClassName)
|
||||
.AndWith(UICondition.CreateFromName(Constants.AppWindowName));
|
||||
|
||||
/// <summary>
|
||||
/// Launch the app
|
||||
/// </summary>
|
||||
public static CalculatorAppLfm Launch()
|
||||
{
|
||||
Log.Comment("Launching Calculator and waiting for first page load...");
|
||||
|
||||
// Need to set this for the MITALite Tap~ methods to work on high DPI screens.
|
||||
UAPApp.SetTestDPIAwareness();
|
||||
|
||||
// We want to be able to see any element in the tree
|
||||
Context.RawContext.Activate();
|
||||
|
||||
// Set default wait timeout.
|
||||
MS.Internal.Mita.Foundation.Waiters.Waiter.DefaultTimeout = TimeSpan.FromSeconds(30);
|
||||
|
||||
// Enable Mita internal logging.
|
||||
MS.Internal.Mita.Foundation.Utilities.Log.OutImplementation = (s, a) => { Log.Comment($"- [MitaLite] { string.Format(s, a) }"); };
|
||||
|
||||
using (EtwWaiter appLaunchWaiter = new EtwWaiter(Constants.CalculatorETWProviderGUID, Constants.AppLaunchEndETWEventName))
|
||||
{
|
||||
var viewDescriptor = NavigationHelper.LaunchApplication(Constants.PackageAppUserModelId);
|
||||
appLaunchWaiter.Wait(TimeSpan.FromSeconds(30));
|
||||
|
||||
Window calculatorWindow = new Window(UIObject.Root.Descendants.Find(CoreWindowUICondition));
|
||||
Debug.Assert(calculatorWindow.ClassName == CoreWindowClassName);
|
||||
|
||||
// Move our window to the foreground.
|
||||
WindowHelper.SetAsForeground(calculatorWindow.GetTopLevelWindow());
|
||||
|
||||
return new CalculatorAppLfm(new CalculatorAppPom(calculatorWindow), viewDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Microsoft.OneCoreUap.Test.AppModel;
|
||||
using MS.Internal.Mita.Foundation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
public class CalculatorAppLfm
|
||||
{
|
||||
private readonly IViewDescriptor viewDescriptor;
|
||||
|
||||
public CalculatorAppLfm(CalculatorAppPom objectModel, IViewDescriptor viewDescriptor)
|
||||
{
|
||||
this.ObjectModel = objectModel;
|
||||
this.viewDescriptor = viewDescriptor;
|
||||
}
|
||||
|
||||
public CalculatorAppPom ObjectModel { get; }
|
||||
|
||||
public MainPageLfm MainPageLfm
|
||||
{
|
||||
get
|
||||
{
|
||||
return new MainPageLfm(this.ObjectModel.MainPagePom);
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
// ObjectModel is essentially the window ui object.
|
||||
if (this.viewDescriptor != null)
|
||||
{
|
||||
NavigationHelper.CloseApplication(this.viewDescriptor.AUMID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using MS.Internal.Mita.Foundation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
public class CalculatorAppPom : UIObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="CalculatorAppPom"/> class.
|
||||
/// </summary>
|
||||
/// <param name="uiObject">UIObject for the calculator app window.</param>
|
||||
public CalculatorAppPom(UIObject uiObject)
|
||||
: base(uiObject)
|
||||
{
|
||||
}
|
||||
public MainPagePom MainPagePom
|
||||
{
|
||||
get
|
||||
{
|
||||
return new MainPagePom(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
public class ContentDialogLfm
|
||||
{
|
||||
public ContentDialogLfm(ContentDialogPom objectModel)
|
||||
{
|
||||
this.ObjectModel = objectModel;
|
||||
}
|
||||
|
||||
public ContentDialogPom ObjectModel { get; }
|
||||
|
||||
public void InvokePrimary()
|
||||
{
|
||||
this.ObjectModel.PrimaryButton.Invoke();
|
||||
}
|
||||
public void InvokeSecondary()
|
||||
{
|
||||
this.ObjectModel.SecondaryButton.Invoke();
|
||||
}
|
||||
|
||||
public void InvokeClose()
|
||||
{
|
||||
this.ObjectModel.CloseButton.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using MS.Internal.Mita.Foundation;
|
||||
using MS.Internal.Mita.Foundation.Controls;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
public class ContentDialogPom : UIObject
|
||||
{
|
||||
private static readonly UICondition textScrollViewerCondition = UICondition.CreateFromId("ContentScrollViewer");
|
||||
private static readonly UICondition titleTextBlockCondition = UICondition.CreateFromClassName("TextBlock");
|
||||
|
||||
private static readonly UICondition primaryButtonCondition =
|
||||
UICondition.CreateFromClassName("Button")
|
||||
.AndWith(UICondition.CreateFromId("PrimaryButton"));
|
||||
private static readonly UICondition secondaryButtonCondition =
|
||||
UICondition.CreateFromClassName("Button")
|
||||
.AndWith(UICondition.CreateFromId("SecondaryButton"));
|
||||
private static readonly UICondition closeButtonCondition =
|
||||
UICondition.CreateFromClassName("Button")
|
||||
.AndWith(UICondition.CreateFromId("CloseButton"));
|
||||
|
||||
public ContentDialogPom(UIObject uiObject) : base(uiObject)
|
||||
{
|
||||
}
|
||||
|
||||
public Button PrimaryButton
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Button(this.Children.Find(primaryButtonCondition));
|
||||
}
|
||||
}
|
||||
|
||||
public Button SecondaryButton
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Button(this.Children.Find(secondaryButtonCondition));
|
||||
}
|
||||
}
|
||||
|
||||
public Button CloseButton
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Button(this.Children.Find(closeButtonCondition));
|
||||
}
|
||||
}
|
||||
|
||||
public string Title
|
||||
{
|
||||
get
|
||||
{
|
||||
var scrollViewer = this.Children.Find(textScrollViewerCondition);
|
||||
var textBlock = scrollViewer.Children.Find(titleTextBlockCondition);
|
||||
return textBlock.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
public class AboutFlyoutLfm : ICanFocusWithClicks
|
||||
{
|
||||
private const string FlyoutId = "FlyoutNav";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AboutFlyoutLfm" /> class.
|
||||
/// </summary>
|
||||
/// <param name="objectModel">The AboutFlyoutPom that represents the About flyout panel.</param>
|
||||
public AboutFlyoutLfm(AboutFlyoutPom objectModel)
|
||||
{
|
||||
this.ObjectModel = objectModel;
|
||||
}
|
||||
|
||||
public AboutFlyoutPom ObjectModel { get; }
|
||||
|
||||
public void FocusWithClicks()
|
||||
{
|
||||
this.ObjectModel.Title.DoubleClick();
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
this.ObjectModel.SendKeys("{ESC}");
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using MS.Internal.Mita.Foundation;
|
||||
using MS.Internal.Mita.Foundation.Controls;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
public class AboutFlyoutPom : UIObject
|
||||
{
|
||||
private const string TitleId = "Header";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AboutFlyoutPom" /> class.
|
||||
/// </summary>
|
||||
/// <param name="uiObject">The UIObject that is the root of the navigation menu.</param>
|
||||
public AboutFlyoutPom(UIObject uiObject) : base(uiObject)
|
||||
{
|
||||
}
|
||||
|
||||
public UIObject Title
|
||||
{
|
||||
get
|
||||
{
|
||||
return new UIObject(this.Descendants.Find(TitleId));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,57 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using MS.Internal.Mita.Foundation;
|
||||
using MS.Internal.Mita.Foundation.Controls;
|
||||
using MS.Internal.Mita.Foundation.Waiters;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the Display section of the calculator modes.
|
||||
/// </summary>
|
||||
public class CalculatorBasePom : UIObject
|
||||
{
|
||||
private const string ExpressionContainerId = "CalculatorExpression";
|
||||
private const string NormalOutputId = "normalOutput";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StandardCalculatorPom" /> class.
|
||||
/// </summary>
|
||||
/// <param name="uiObject">The UIObject that is the root of the standard calculator.</param>
|
||||
public CalculatorBasePom(UIObject uiObject) : base(uiObject)
|
||||
{
|
||||
}
|
||||
|
||||
public TextBlock Expression
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TextBlock(this.Descendants.Find(ExpressionContainerId));
|
||||
}
|
||||
}
|
||||
|
||||
public UIEventWaiter GetExpressionChangedWaiter()
|
||||
{
|
||||
return new PropertyChangedEventWaiter(this.Expression, UIProperty.Get("Name"));
|
||||
}
|
||||
|
||||
public TextBlock Display
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TextBlock(this.Descendants.Find(NormalOutputId));
|
||||
}
|
||||
}
|
||||
|
||||
public UIEventWaiter GetDisplayChangedWaiter()
|
||||
{
|
||||
return new PropertyChangedEventWaiter(this.Display, UIProperty.Get("Name"));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
public class DateCalculatorLfm
|
||||
{
|
||||
public DateCalculatorLfm(DateCalculatorPom dateCalculatorPom)
|
||||
{
|
||||
this.ObjectModel = dateCalculatorPom;
|
||||
}
|
||||
|
||||
public DateCalculatorPom ObjectModel { get; }
|
||||
|
||||
public void EnsureDateDifferenceMode()
|
||||
{
|
||||
this.OpenModeSelector();
|
||||
this.ObjectModel.ModeSelector.AllItems[0].Select();
|
||||
}
|
||||
|
||||
public void EnsureAddSubtractMode()
|
||||
{
|
||||
this.OpenModeSelector();
|
||||
this.ObjectModel.ModeSelector.AllItems[1].Select();
|
||||
}
|
||||
|
||||
private void OpenModeSelector()
|
||||
{
|
||||
using (var waiter = this.ObjectModel.ModeSelector.GetExpandedWaiter())
|
||||
{
|
||||
this.ObjectModel.ModeSelector.Expand();
|
||||
waiter.TryWait();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using MS.Internal.Mita.Foundation;
|
||||
using MS.Internal.Mita.Foundation.Controls;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
public class DateCalculatorPom : UIObject
|
||||
{
|
||||
private const string ModeSelectorId = "DateCalculationOption";
|
||||
|
||||
public DateCalculatorPom(UIObject uiObject) : base(uiObject)
|
||||
{
|
||||
}
|
||||
|
||||
public ComboBox ModeSelector
|
||||
{
|
||||
get
|
||||
{
|
||||
return new ComboBox(this.Descendants.Find(ModeSelectorId));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,255 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Etw.Managed;
|
||||
using MS.Internal.Mita.Foundation.Waiters;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
public class MainPageLfm : ICanFocusWithClicks
|
||||
{
|
||||
public MainPageLfm(MainPagePom objectModel)
|
||||
{
|
||||
this.ObjectModel = objectModel;
|
||||
}
|
||||
|
||||
public MainPagePom ObjectModel { get; }
|
||||
|
||||
public NavBarLfm OpenNavBar()
|
||||
{
|
||||
using (EtwWaiter waiter = this.ObjectModel.GetNavBarOpenedWaiter())
|
||||
{
|
||||
this.ObjectModel.NavButton.Invoke();
|
||||
waiter.Wait();
|
||||
}
|
||||
|
||||
return new NavBarLfm(this.ObjectModel.NavBarPom);
|
||||
}
|
||||
|
||||
public void CloseNavBar()
|
||||
{
|
||||
this.ObjectModel.NavBarPom.CloseButton.Invoke();
|
||||
}
|
||||
|
||||
public void FocusWithClicks()
|
||||
{
|
||||
this.ObjectModel.Header.DoubleClick();
|
||||
}
|
||||
|
||||
public StandardCalculatorLfm NavigateToStandardCalculator()
|
||||
{
|
||||
var navBar = this.OpenNavBar();
|
||||
using (var waiter = this.ObjectModel.GetModeChangedWaiter())
|
||||
{
|
||||
navBar.SelectStandard();
|
||||
waiter.TryWait();
|
||||
}
|
||||
|
||||
return new StandardCalculatorLfm(this.ObjectModel.StandardCalculatorPom);
|
||||
}
|
||||
|
||||
public ScientificCalculatorLfm NavigateToScientificCalculator()
|
||||
{
|
||||
var navBar = this.OpenNavBar();
|
||||
using (var waiter = this.ObjectModel.GetModeChangedWaiter())
|
||||
{
|
||||
navBar.SelectScientific();
|
||||
waiter.TryWait();
|
||||
}
|
||||
|
||||
return new ScientificCalculatorLfm(this.ObjectModel.ScientificCalculatorPom);
|
||||
}
|
||||
|
||||
public ProgrammerCalculatorLfm NavigateToProgrammerCalculator()
|
||||
{
|
||||
var navBar = this.OpenNavBar();
|
||||
using (var waiter = this.ObjectModel.GetModeChangedWaiter())
|
||||
{
|
||||
navBar.SelectProgrammer();
|
||||
waiter.TryWait();
|
||||
}
|
||||
|
||||
return new ProgrammerCalculatorLfm(this.ObjectModel.ProgrammerCalculatorPom);
|
||||
}
|
||||
|
||||
public DateCalculatorLfm NavigateToDateCalculator()
|
||||
{
|
||||
var navBar = this.OpenNavBar();
|
||||
using (var waiter = this.ObjectModel.GetModeChangedWaiter())
|
||||
{
|
||||
navBar.SelectDate();
|
||||
waiter.TryWait();
|
||||
}
|
||||
|
||||
return new DateCalculatorLfm(this.ObjectModel.DateCalculatorPom);
|
||||
}
|
||||
|
||||
public UnitConverterLfm NavigateToCurrencyConverter()
|
||||
{
|
||||
var navBar = this.OpenNavBar();
|
||||
using (var waiter = this.ObjectModel.GetModeChangedWaiter())
|
||||
{
|
||||
navBar.SelectCurrency();
|
||||
waiter.TryWait();
|
||||
}
|
||||
|
||||
return new UnitConverterLfm(this.ObjectModel.UnitConverterPom);
|
||||
}
|
||||
|
||||
public UnitConverterLfm NavigateToVolumeConverter()
|
||||
{
|
||||
var navBar = this.OpenNavBar();
|
||||
using (var waiter = this.ObjectModel.GetModeChangedWaiter())
|
||||
{
|
||||
navBar.SelectVolume();
|
||||
waiter.TryWait();
|
||||
}
|
||||
|
||||
return new UnitConverterLfm(this.ObjectModel.UnitConverterPom);
|
||||
}
|
||||
|
||||
public UnitConverterLfm NavigateToLengthConverter()
|
||||
{
|
||||
var navBar = this.OpenNavBar();
|
||||
using (var waiter = this.ObjectModel.GetModeChangedWaiter())
|
||||
{
|
||||
navBar.SelectLength();
|
||||
waiter.TryWait();
|
||||
}
|
||||
|
||||
return new UnitConverterLfm(this.ObjectModel.UnitConverterPom);
|
||||
}
|
||||
|
||||
public UnitConverterLfm NavigateToWeightConverter()
|
||||
{
|
||||
var navBar = this.OpenNavBar();
|
||||
using (var waiter = this.ObjectModel.GetModeChangedWaiter())
|
||||
{
|
||||
navBar.SelectWeight();
|
||||
waiter.TryWait();
|
||||
}
|
||||
|
||||
return new UnitConverterLfm(this.ObjectModel.UnitConverterPom);
|
||||
}
|
||||
|
||||
public UnitConverterLfm NavigateToTemperatureConverter()
|
||||
{
|
||||
var navBar = this.OpenNavBar();
|
||||
using (var waiter = this.ObjectModel.GetModeChangedWaiter())
|
||||
{
|
||||
navBar.SelectTemperature();
|
||||
waiter.TryWait();
|
||||
}
|
||||
|
||||
return new UnitConverterLfm(this.ObjectModel.UnitConverterPom);
|
||||
}
|
||||
|
||||
public UnitConverterLfm NavigateToEnergyConverter()
|
||||
{
|
||||
var navBar = this.OpenNavBar();
|
||||
using (var waiter = this.ObjectModel.GetModeChangedWaiter())
|
||||
{
|
||||
navBar.SelectEnergy();
|
||||
waiter.TryWait();
|
||||
}
|
||||
|
||||
return new UnitConverterLfm(this.ObjectModel.UnitConverterPom);
|
||||
}
|
||||
|
||||
public UnitConverterLfm NavigateToAreaConverter()
|
||||
{
|
||||
var navBar = this.OpenNavBar();
|
||||
using (var waiter = this.ObjectModel.GetModeChangedWaiter())
|
||||
{
|
||||
navBar.SelectArea();
|
||||
waiter.TryWait();
|
||||
}
|
||||
|
||||
return new UnitConverterLfm(this.ObjectModel.UnitConverterPom);
|
||||
}
|
||||
|
||||
public UnitConverterLfm NavigateToSpeedConverter()
|
||||
{
|
||||
var navBar = this.OpenNavBar();
|
||||
using (var waiter = this.ObjectModel.GetModeChangedWaiter())
|
||||
{
|
||||
navBar.SelectSpeed();
|
||||
waiter.TryWait();
|
||||
}
|
||||
|
||||
return new UnitConverterLfm(this.ObjectModel.UnitConverterPom);
|
||||
}
|
||||
|
||||
public UnitConverterLfm NavigateToTimeConverter()
|
||||
{
|
||||
var navBar = this.OpenNavBar();
|
||||
using (var waiter = this.ObjectModel.GetModeChangedWaiter())
|
||||
{
|
||||
navBar.SelectTime();
|
||||
waiter.TryWait();
|
||||
}
|
||||
|
||||
return new UnitConverterLfm(this.ObjectModel.UnitConverterPom);
|
||||
}
|
||||
|
||||
public UnitConverterLfm NavigateToPowerConverter()
|
||||
{
|
||||
var navBar = this.OpenNavBar();
|
||||
using (var waiter = this.ObjectModel.GetModeChangedWaiter())
|
||||
{
|
||||
navBar.SelectPower();
|
||||
waiter.TryWait();
|
||||
}
|
||||
|
||||
return new UnitConverterLfm(this.ObjectModel.UnitConverterPom);
|
||||
}
|
||||
|
||||
public UnitConverterLfm NavigateToDataConverter()
|
||||
{
|
||||
var navBar = this.OpenNavBar();
|
||||
using (var waiter = this.ObjectModel.GetModeChangedWaiter())
|
||||
{
|
||||
navBar.SelectData();
|
||||
waiter.TryWait();
|
||||
}
|
||||
|
||||
return new UnitConverterLfm(this.ObjectModel.UnitConverterPom);
|
||||
}
|
||||
|
||||
public UnitConverterLfm NavigateToPressureConverter()
|
||||
{
|
||||
var navBar = this.OpenNavBar();
|
||||
using (var waiter = this.ObjectModel.GetModeChangedWaiter())
|
||||
{
|
||||
navBar.SelectPressure();
|
||||
waiter.TryWait();
|
||||
}
|
||||
|
||||
return new UnitConverterLfm(this.ObjectModel.UnitConverterPom);
|
||||
}
|
||||
|
||||
public UnitConverterLfm NavigateToAngleConverter()
|
||||
{
|
||||
var navBar = this.OpenNavBar();
|
||||
using (var waiter = this.ObjectModel.GetModeChangedWaiter())
|
||||
{
|
||||
navBar.SelectAngle();
|
||||
waiter.TryWait();
|
||||
}
|
||||
|
||||
return new UnitConverterLfm(this.ObjectModel.UnitConverterPom);
|
||||
}
|
||||
|
||||
public AboutFlyoutLfm OpenAboutFlyout()
|
||||
{
|
||||
var navBar = this.OpenNavBar();
|
||||
using (EtwWaiter waiter = new EtwWaiter(Constants.CalculatorETWProviderGUID, Constants.AboutFlyoutOpenedETWEventName))
|
||||
{
|
||||
navBar.SelectAbout();
|
||||
waiter.Wait();
|
||||
}
|
||||
|
||||
return new AboutFlyoutLfm(this.ObjectModel.AboutFlyoutPom);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Etw.Managed;
|
||||
using MS.Internal.Mita.Foundation;
|
||||
using MS.Internal.Mita.Foundation.Controls;
|
||||
using MS.Internal.Mita.Foundation.Waiters;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Physical Object Model for the app window.
|
||||
/// POM is the implementation model of the app.
|
||||
/// See following references to POM:
|
||||
/// * https://blogs.msdn.microsoft.com/wltester/2011/11/14/object-model-design/
|
||||
/// * https://blogs.msdn.microsoft.com/micahel/2005/06/03/how-do-i-invoke-thee-let-me-count-the-ways-the-physical-object-model/
|
||||
/// See https://en.wikipedia.org/wiki/Model-based_testing for model-based testing.
|
||||
/// </summary>
|
||||
public class MainPagePom : UIObject
|
||||
{
|
||||
private const string NavButtonId = "TogglePaneButton";
|
||||
private const string SplitViewPaneRootId = "PaneRoot";
|
||||
private const string NavBarFlyoutId = "FlyoutNav";
|
||||
private const string HeaderId = "Header";
|
||||
private const string AboutPageFlyoutId = "AboutPageFlyout";
|
||||
|
||||
public MainPagePom(UIObject uiObject)
|
||||
: base(uiObject)
|
||||
{
|
||||
}
|
||||
|
||||
public Button NavButton => new Button(this.Descendants.Find(UICondition.CreateFromId(NavButtonId)));
|
||||
|
||||
public UIObject Header => new UIObject(this.Descendants.Find(HeaderId));
|
||||
|
||||
public NavBarPom NavBarPom => new NavBarPom(this.Children.Find(SplitViewPaneRootId));
|
||||
|
||||
public EtwWaiter GetNavBarOpenedWaiter() => new EtwWaiter(Constants.CalculatorETWProviderGUID, Constants.NavBarOpenedETWEventName);
|
||||
|
||||
public StandardCalculatorPom StandardCalculatorPom => new StandardCalculatorPom(this);
|
||||
|
||||
public ScientificCalculatorPom ScientificCalculatorPom => new ScientificCalculatorPom(this);
|
||||
|
||||
public ProgrammerCalculatorPom ProgrammerCalculatorPom => new ProgrammerCalculatorPom(this);
|
||||
|
||||
public DateCalculatorPom DateCalculatorPom => new DateCalculatorPom(this);
|
||||
|
||||
public UnitConverterPom UnitConverterPom => new UnitConverterPom(this);
|
||||
|
||||
public AboutFlyoutPom AboutFlyoutPom => new AboutFlyoutPom(this.Descendants.Find(AboutPageFlyoutId));
|
||||
|
||||
public EtwWaiter GetModeChangedWaiter() => new EtwWaiter(Constants.CalculatorETWProviderGUID, Constants.AppModeChangeEndETWEventName);
|
||||
}
|
||||
}
|
@@ -0,0 +1,144 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Windows.Automation;
|
||||
using MS.Internal.Mita.Foundation;
|
||||
using MS.Internal.Mita.Foundation.Controls;
|
||||
using MS.Internal.Mita.Foundation.Patterns;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the NavBar of the Calculator app.
|
||||
/// </summary>
|
||||
public class NavBarLfm : ICanFocusWithClicks
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="NavBarLfm" /> class.
|
||||
/// </summary>
|
||||
/// <param name="objectModel">The NavBarPom that represents the NavBar.</param>
|
||||
public NavBarLfm(NavBarPom objectModel)
|
||||
{
|
||||
this.ObjectModel = objectModel;
|
||||
}
|
||||
|
||||
public NavBarPom ObjectModel { get; }
|
||||
|
||||
public void SelectStandard()
|
||||
{
|
||||
SelectItem(this.ObjectModel.StandardMenuItem);
|
||||
}
|
||||
|
||||
public void SelectScientific()
|
||||
{
|
||||
SelectItem(this.ObjectModel.ScientificMenuItem);
|
||||
}
|
||||
|
||||
public void SelectProgrammer()
|
||||
{
|
||||
SelectItem(this.ObjectModel.ProgrammerMenuItem);
|
||||
}
|
||||
|
||||
public void SelectDate()
|
||||
{
|
||||
SelectItem(this.ObjectModel.DateMenuItem);
|
||||
}
|
||||
|
||||
public void SelectCurrency()
|
||||
{
|
||||
SelectItem(this.ObjectModel.CurrencyMenuItem);
|
||||
}
|
||||
|
||||
public void SelectVolume()
|
||||
{
|
||||
SelectItem(this.ObjectModel.VolumeMenuItem);
|
||||
}
|
||||
|
||||
public void SelectLength()
|
||||
{
|
||||
SelectItem(this.ObjectModel.LengthMenuItem);
|
||||
}
|
||||
|
||||
public void SelectWeight()
|
||||
{
|
||||
SelectItem(this.ObjectModel.WeightMenuItem);
|
||||
}
|
||||
|
||||
public void SelectTemperature()
|
||||
{
|
||||
SelectItem(this.ObjectModel.TemperatureMenuItem);
|
||||
}
|
||||
|
||||
public void SelectEnergy()
|
||||
{
|
||||
SelectItem(this.ObjectModel.EnergyMenuItem);
|
||||
}
|
||||
|
||||
public void SelectArea()
|
||||
{
|
||||
SelectItem(this.ObjectModel.AreaMenuItem);
|
||||
}
|
||||
|
||||
public void SelectSpeed()
|
||||
{
|
||||
SelectItem(this.ObjectModel.SpeedMenuItem);
|
||||
}
|
||||
|
||||
public void SelectTime()
|
||||
{
|
||||
SelectItem(this.ObjectModel.TimeMenuItem);
|
||||
}
|
||||
|
||||
public void SelectPower()
|
||||
{
|
||||
SelectItem(this.ObjectModel.PowerMenuItem);
|
||||
}
|
||||
|
||||
public void SelectData()
|
||||
{
|
||||
SelectItem(this.ObjectModel.DataMenuItem);
|
||||
}
|
||||
|
||||
public void SelectPressure()
|
||||
{
|
||||
SelectItem(this.ObjectModel.PressureMenuItem);
|
||||
}
|
||||
|
||||
public void SelectAngle()
|
||||
{
|
||||
SelectItem(this.ObjectModel.AngleMenuItem);
|
||||
}
|
||||
|
||||
public void SelectAbout()
|
||||
{
|
||||
this.ObjectModel.AboutButton.Invoke();
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
this.ObjectModel.CloseButton.Invoke();
|
||||
}
|
||||
|
||||
public void FocusWithClicks()
|
||||
{
|
||||
// To focus (for AccSpot) without changing anything, click to the right of the close button.
|
||||
Button button = this.ObjectModel.CloseButton;
|
||||
int xPos = button.BoundingRectangle.Width + Constants.ClickMargin;
|
||||
int yPos = button.BoundingRectangle.Height / 2;
|
||||
button.DoubleClick(PointerButtons.Primary, xPos, yPos);
|
||||
}
|
||||
|
||||
private void SelectItem(ListViewItem item)
|
||||
{
|
||||
if (item.IsSelected)
|
||||
{
|
||||
this.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
item.Select();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,96 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Linq;
|
||||
using MS.Internal.Mita.Foundation;
|
||||
using MS.Internal.Mita.Foundation.Controls;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the navigation menu.
|
||||
/// </summary>
|
||||
public class NavBarPom : UIObject
|
||||
{
|
||||
private const string StandardId = "Standard";
|
||||
private const string ScientificId = "Scientific";
|
||||
private const string ProgrammerId = "Programmer";
|
||||
private const string DateId = "Date";
|
||||
private const string CurrencyId = "Currency";
|
||||
private const string VolumeId = "Volume";
|
||||
private const string LengthId = "Length";
|
||||
private const string WeightId = "Weight";
|
||||
private const string TemperatureId = "Temperature";
|
||||
private const string EnergyId = "Energy";
|
||||
private const string AreaId = "Area";
|
||||
private const string SpeedId = "Speed";
|
||||
private const string TimeId = "Time";
|
||||
private const string PowerId = "Power";
|
||||
private const string DataId = "Data";
|
||||
private const string PressureId = "Pressure";
|
||||
private const string AngleId = "Angle";
|
||||
private const string AboutId = "AboutButton";
|
||||
private const string CloseId = "TogglePaneButton";
|
||||
private const string FlyoutListViewId = "MenuItemsHost";
|
||||
private const string ConverterSectionId = "Converter";
|
||||
private const string ConverterTextKey = "ConverterModeText";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="NavBarPom" /> class.
|
||||
/// </summary>
|
||||
/// <param name="uiObject">The UIObject that is the root of the navigation menu.</param>
|
||||
public NavBarPom(UIObject uiObject) : base(uiObject)
|
||||
{
|
||||
}
|
||||
|
||||
public ListViewItem StandardMenuItem => ScrollAndGetItem(StandardId);
|
||||
|
||||
public ListViewItem ScientificMenuItem => ScrollAndGetItem(ScientificId);
|
||||
|
||||
public ListViewItem ProgrammerMenuItem => ScrollAndGetItem(ProgrammerId);
|
||||
|
||||
public ListViewItem DateMenuItem => ScrollAndGetItem(DateId);
|
||||
|
||||
public ListViewItem CurrencyMenuItem => ScrollAndGetItem(CurrencyId);
|
||||
|
||||
public ListViewItem VolumeMenuItem => ScrollAndGetItem(VolumeId);
|
||||
|
||||
public ListViewItem LengthMenuItem => ScrollAndGetItem(LengthId);
|
||||
|
||||
public ListViewItem WeightMenuItem => ScrollAndGetItem(WeightId);
|
||||
|
||||
public ListViewItem TemperatureMenuItem => ScrollAndGetItem(TemperatureId);
|
||||
|
||||
public ListViewItem EnergyMenuItem => ScrollAndGetItem(EnergyId);
|
||||
|
||||
public ListViewItem AreaMenuItem => ScrollAndGetItem(AreaId);
|
||||
|
||||
public ListViewItem SpeedMenuItem => ScrollAndGetItem(SpeedId);
|
||||
|
||||
public ListViewItem TimeMenuItem => ScrollAndGetItem(TimeId);
|
||||
|
||||
public ListViewItem PowerMenuItem => ScrollAndGetItem(PowerId);
|
||||
|
||||
public ListViewItem DataMenuItem => ScrollAndGetItem(DataId);
|
||||
|
||||
public ListViewItem PressureMenuItem => ScrollAndGetItem(PressureId);
|
||||
|
||||
public ListViewItem AngleMenuItem => ScrollAndGetItem(AngleId);
|
||||
|
||||
public Button AboutButton => new Button(this.Descendants.Find(AboutId));
|
||||
|
||||
public Button CloseButton => new Button(this.Parent.Children.Find(CloseId));
|
||||
|
||||
public ListView ModeListView => new ListView(this.Descendants.Find(FlyoutListViewId));
|
||||
|
||||
private ListViewItem ScrollAndGetItem(string id)
|
||||
{
|
||||
ListViewItem item;
|
||||
var res = this.ModeListView.AllItems.TryFind(id, out item);
|
||||
|
||||
item.ScrollIntoView();
|
||||
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,56 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using MS.Internal.Mita.Foundation.Waiters;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
public class ProgrammerCalculatorLfm
|
||||
{
|
||||
public ProgrammerCalculatorLfm(ProgrammerCalculatorPom programmerCalculatorPom)
|
||||
{
|
||||
this.ObjectModel = programmerCalculatorPom;
|
||||
}
|
||||
|
||||
public ProgrammerCalculatorPom ObjectModel { get; }
|
||||
|
||||
public void EnsureFullKeypad()
|
||||
{
|
||||
if (!this.ObjectModel.FullKeypadButton.IsSelected)
|
||||
{
|
||||
this.ObjectModel.FullKeypadButton.Select();
|
||||
}
|
||||
}
|
||||
|
||||
public void EnsureBitTogglingKeypad()
|
||||
{
|
||||
if (!this.ObjectModel.BitFlipKeypadButton.IsSelected)
|
||||
{
|
||||
this.ObjectModel.BitFlipKeypadButton.Select();
|
||||
}
|
||||
}
|
||||
|
||||
public void ChangeBitLength()
|
||||
{
|
||||
this.ObjectModel.GetCurrentBitLengthButton().Invoke();
|
||||
}
|
||||
|
||||
public MemoryLfm OpenMemory()
|
||||
{
|
||||
MemoryLfm lfm = new MemoryLfm(this.ObjectModel.MemoryControls);
|
||||
lfm.OpenBody();
|
||||
return lfm;
|
||||
}
|
||||
|
||||
public void FiveMemorySet()
|
||||
{
|
||||
using (UIEventWaiter waiter = this.ObjectModel.GetDisplayChangedWaiter())
|
||||
{
|
||||
this.ObjectModel.NumberPad.FiveButton.Invoke();
|
||||
waiter.TryWait();
|
||||
}
|
||||
|
||||
this.ObjectModel.MemoryControls.SetButton.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,56 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using MS.Internal.Mita.Foundation;
|
||||
using MS.Internal.Mita.Foundation.Controls;
|
||||
using MS.Internal.Mita.Foundation.Waiters;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
public class ProgrammerCalculatorPom : UIObject
|
||||
{
|
||||
private const string FullKeypadButtonId = "fullKeypad";
|
||||
private const string BitFlipKeypadButtonId = "bitFlip";
|
||||
private const string CalculatorResultsId = "CalculatorResults";
|
||||
private const string NumberPadId = "NumberPad";
|
||||
|
||||
private readonly string[] BitLengthButtonIds =
|
||||
{
|
||||
"qwordButton",
|
||||
"dwordButton",
|
||||
"wordButton",
|
||||
"byteButton"
|
||||
};
|
||||
|
||||
public ProgrammerCalculatorPom(UIObject uiObject) : base(uiObject)
|
||||
{
|
||||
}
|
||||
|
||||
public NumberPadPom NumberPad => new NumberPadPom(this.Descendants.Find(NumberPadId));
|
||||
|
||||
public MemoryPom MemoryControls => new MemoryPom(this);
|
||||
|
||||
public RadioButton FullKeypadButton => new RadioButton(this.Descendants.Find(FullKeypadButtonId));
|
||||
|
||||
public RadioButton BitFlipKeypadButton => new RadioButton(this.Descendants.Find(BitFlipKeypadButtonId));
|
||||
|
||||
public TextBlock Display => new TextBlock(this.Descendants.Find(CalculatorResultsId));
|
||||
|
||||
public UIEventWaiter GetDisplayChangedWaiter() => this.Display.GetNameChangedWaiter();
|
||||
|
||||
public Button GetCurrentBitLengthButton()
|
||||
{
|
||||
// There are four bit length buttons, with only one visible at a time.
|
||||
UIObject button = null;
|
||||
foreach (var buttonId in this.BitLengthButtonIds)
|
||||
{
|
||||
if (this.Descendants.TryFind(buttonId, out button))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new Button(button);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,138 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using MS.Internal.Mita.Foundation.Waiters;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using WEX.Logging.Interop;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the Standard calculator view.
|
||||
/// </summary>
|
||||
public class ScientificCalculatorLfm
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ScientificCalculatorLfm" /> class.
|
||||
/// </summary>
|
||||
/// <param name="uiObject">The UIObject that is the root of the scientific Calculator.</param>
|
||||
public ScientificCalculatorLfm(ScientificCalculatorPom objectModel)
|
||||
{
|
||||
this.ObjectModel = objectModel;
|
||||
}
|
||||
|
||||
public ScientificCalculatorPom ObjectModel { get; }
|
||||
|
||||
public void Press1()
|
||||
{
|
||||
using (UIEventWaiter waiter = this.ObjectModel.GetDisplayChangedWaiter())
|
||||
{
|
||||
Log.Comment("Invoking 1");
|
||||
this.ObjectModel.OneButton.Invoke();
|
||||
waiter.TryWait();
|
||||
}
|
||||
}
|
||||
|
||||
public void Press2()
|
||||
{
|
||||
using (UIEventWaiter waiter = this.ObjectModel.GetDisplayChangedWaiter())
|
||||
{
|
||||
Log.Comment("Invoking 2");
|
||||
this.ObjectModel.NumberPad.TwoButton.Invoke();
|
||||
waiter.TryWait();
|
||||
}
|
||||
}
|
||||
|
||||
public void Press3()
|
||||
{
|
||||
using (UIEventWaiter waiter = this.ObjectModel.GetDisplayChangedWaiter())
|
||||
{
|
||||
Log.Comment("Invoking 3");
|
||||
this.ObjectModel.ThreeButton.Invoke();
|
||||
waiter.TryWait();
|
||||
}
|
||||
}
|
||||
|
||||
public void Press4()
|
||||
{
|
||||
using (UIEventWaiter waiter = this.ObjectModel.GetDisplayChangedWaiter())
|
||||
{
|
||||
Log.Comment("Invoking 4");
|
||||
this.ObjectModel.FourButton.Invoke();
|
||||
waiter.TryWait();
|
||||
}
|
||||
}
|
||||
|
||||
public void PressSqrt()
|
||||
{
|
||||
// When invoking sqrt, both the expression changes.
|
||||
using (UIEventWaiter waiter = this.ObjectModel.GetExpressionChangedWaiter())
|
||||
{
|
||||
Log.Comment("Invoking sqrt");
|
||||
this.ObjectModel.SqrtButton.Invoke();
|
||||
waiter.TryWait();
|
||||
}
|
||||
}
|
||||
|
||||
public void PressMinus()
|
||||
{
|
||||
using (UIEventWaiter waiter = this.ObjectModel.GetExpressionChangedWaiter())
|
||||
{
|
||||
Log.Comment("Invoking minus");
|
||||
this.ObjectModel.MinusButton.Invoke();
|
||||
waiter.TryWait();
|
||||
}
|
||||
}
|
||||
|
||||
public void PressPlus()
|
||||
{
|
||||
using (UIEventWaiter waiter = this.ObjectModel.GetExpressionChangedWaiter())
|
||||
{
|
||||
Log.Comment("Invoking plus");
|
||||
this.ObjectModel.PlusButton.Invoke();
|
||||
waiter.TryWait();
|
||||
}
|
||||
}
|
||||
|
||||
public void PressEquals()
|
||||
{
|
||||
// When invoking equals, both the display and the expression change.
|
||||
using (UIEventWaiter expressionWaiter = this.ObjectModel.GetExpressionChangedWaiter())
|
||||
using (UIEventWaiter displayWaiter = this.ObjectModel.GetDisplayChangedWaiter())
|
||||
{
|
||||
Log.Comment("Invoking equals");
|
||||
this.ObjectModel.EqualButton.Invoke();
|
||||
expressionWaiter.TryWait();
|
||||
displayWaiter.TryWait();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnePlusTwoEnter()
|
||||
{
|
||||
Press1();
|
||||
PressPlus();
|
||||
Press2();
|
||||
PressEquals();
|
||||
}
|
||||
|
||||
public void MemorySet() => this.ObjectModel.MemoryControls.SetButton.Invoke();
|
||||
|
||||
public MemoryLfm OpenMemory()
|
||||
{
|
||||
MemoryLfm lfm = new MemoryLfm(this.ObjectModel.MemoryControls);
|
||||
lfm.OpenBody();
|
||||
return lfm;
|
||||
}
|
||||
|
||||
public HistoryLfm OpenHistory()
|
||||
{
|
||||
HistoryLfm lfm = new HistoryLfm(this.ObjectModel.HistoryControls);
|
||||
lfm.OpenBody();
|
||||
return lfm;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using MS.Internal.Mita.Foundation;
|
||||
using MS.Internal.Mita.Foundation.Controls;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the Scientific Calculator
|
||||
/// </summary>
|
||||
public class ScientificCalculatorPom : CalculatorBasePom
|
||||
{
|
||||
private const string NumberPadId = "NumberPad";
|
||||
private const string StandardOperatorsId = "StandardOperators";
|
||||
private const string DisplayControlsId = "DisplayControls";
|
||||
private const string ScientificFunctionsId = "ScientificFunctions";
|
||||
private const string OneButtonId = "num1Button";
|
||||
private const string ThreeButtonId = "num3Button";
|
||||
private const string FourButtonId = "num4Button";
|
||||
private const string SqrtButtonId = "squareRootButton";
|
||||
private const string MinusButtonId = "minusButton";
|
||||
private const string PlusButtonId = "plusButton";
|
||||
private const string EqualButtonId = "equalButton";
|
||||
private const string ClearButtonId = "clearButton";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ScientificCalculatorPom" /> class.
|
||||
/// </summary>
|
||||
/// <param name="uiObject">The UIObject that is the root of the scientific calculator.</param>
|
||||
public ScientificCalculatorPom(UIObject uiObject) : base(uiObject)
|
||||
{
|
||||
}
|
||||
|
||||
public UIObject StandardOperatorsGroup => this.Descendants.Find(StandardOperatorsId);
|
||||
|
||||
public UIObject DisplayControlsGroup => this.Descendants.Find(DisplayControlsId);
|
||||
|
||||
public UIObject ScientificFunctionsGroup => this.Descendants.Find(ScientificFunctionsId);
|
||||
|
||||
public Button OneButton => this.NumberPad.OneButton;
|
||||
|
||||
public Button ThreeButton => this.NumberPad.ThreeButton;
|
||||
|
||||
public Button FourButton => this.NumberPad.FourButton;
|
||||
|
||||
public Button SqrtButton => new Button(this.ScientificFunctionsGroup.Children.Find(SqrtButtonId));
|
||||
|
||||
public Button MinusButton => new Button(this.StandardOperatorsGroup.Children.Find(MinusButtonId));
|
||||
|
||||
public Button PlusButton => new Button(this.StandardOperatorsGroup.Children.Find(PlusButtonId));
|
||||
|
||||
public Button EqualButton => new Button(this.StandardOperatorsGroup.Children.Find(EqualButtonId));
|
||||
|
||||
public Button ClearButton => new Button(this.DisplayControlsGroup.Children.Find(ClearButtonId));
|
||||
|
||||
public NumberPadPom NumberPad => new NumberPadPom(this.Descendants.Find(NumberPadId));
|
||||
|
||||
public HistoryPom HistoryControls => new HistoryPom(this);
|
||||
|
||||
public MemoryPom MemoryControls => new MemoryPom(this);
|
||||
}
|
||||
}
|
@@ -0,0 +1,94 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using MS.Internal.Mita.Foundation.Waiters;
|
||||
using WEX.Logging.Interop;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the Standard calculator view.
|
||||
/// </summary>
|
||||
public class StandardCalculatorLfm
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StandardCalculatorLfm" /> class.
|
||||
/// </summary>
|
||||
/// <param name="uiObject">The UIObject that is the root of the Standard Calculator.</param>
|
||||
public StandardCalculatorLfm(StandardCalculatorPom objectModel)
|
||||
{
|
||||
this.ObjectModel = objectModel;
|
||||
}
|
||||
|
||||
public StandardCalculatorPom ObjectModel { get; }
|
||||
|
||||
public void OnePlusTwoEnter()
|
||||
{
|
||||
using (UIEventWaiter waiter = this.ObjectModel.GetDisplayChangedWaiter())
|
||||
{
|
||||
Log.Comment("Invoking 1");
|
||||
this.ObjectModel.NumPad.OneButton.Invoke();
|
||||
waiter.TryWait();
|
||||
}
|
||||
using (UIEventWaiter waiter = this.ObjectModel.GetExpressionChangedWaiter())
|
||||
{
|
||||
Log.Comment("Pressing +");
|
||||
this.ObjectModel.SendKeys("{ADD}");
|
||||
// PropertyChangeWaiter is unreliable for the first name changed notification
|
||||
// Bug 17624996: PropertyChanged event not fired when Name is updated for the first time for a control with custom automation peer.
|
||||
waiter.TryWait();
|
||||
}
|
||||
using (UIEventWaiter waiter = this.ObjectModel.GetDisplayChangedWaiter())
|
||||
{
|
||||
Log.Comment("Pressing 2");
|
||||
this.ObjectModel.SendKeys("2");
|
||||
waiter.TryWait();
|
||||
}
|
||||
// When pressing enter, both the display and the expression change.
|
||||
using (UIEventWaiter expressionWaiter = this.ObjectModel.GetExpressionChangedWaiter())
|
||||
using (UIEventWaiter displayWaiter = this.ObjectModel.GetDisplayChangedWaiter())
|
||||
{
|
||||
Log.Comment("Invoking equals");
|
||||
this.ObjectModel.EqualButton.Invoke();
|
||||
expressionWaiter.TryWait();
|
||||
displayWaiter.TryWait();
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
using (UIEventWaiter waiter = this.ObjectModel.GetDisplayChangedWaiter())
|
||||
{
|
||||
Log.Comment("Pressing escape");
|
||||
this.ObjectModel.ClearButton.Invoke();
|
||||
waiter.TryWait();
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearFiveMemorySet()
|
||||
{
|
||||
this.Clear();
|
||||
using (UIEventWaiter waiter = this.ObjectModel.GetDisplayChangedWaiter())
|
||||
{
|
||||
this.ObjectModel.NumPad.FiveButton.Invoke();
|
||||
waiter.TryWait();
|
||||
}
|
||||
|
||||
this.ObjectModel.MemoryControls.SetButton.Invoke();
|
||||
}
|
||||
|
||||
public MemoryLfm OpenMemory()
|
||||
{
|
||||
MemoryLfm lfm = new MemoryLfm(this.ObjectModel.MemoryControls);
|
||||
lfm.OpenBody();
|
||||
return lfm;
|
||||
}
|
||||
|
||||
public HistoryLfm OpenHistory()
|
||||
{
|
||||
HistoryLfm lfm = new HistoryLfm(this.ObjectModel.HistoryControls);
|
||||
lfm.OpenBody();
|
||||
return lfm;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using MS.Internal.Mita.Foundation;
|
||||
using MS.Internal.Mita.Foundation.Controls;
|
||||
using MS.Internal.Mita.Foundation.Waiters;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the Standard Calculator
|
||||
/// </summary>
|
||||
public class StandardCalculatorPom : CalculatorBasePom
|
||||
{
|
||||
private const string CalculatorResultsId = "CalculatorResults";
|
||||
private const string ExpressionContainerId = "CalculatorExpression";
|
||||
private const string NumberPadId = "NumberPad";
|
||||
private const string StandardOperatorsId = "StandardOperators";
|
||||
private const string DisplayControlsId = "DisplayControls";
|
||||
private const string EqualButtonId = "equalButton";
|
||||
private const string ClearButtonId = "clearButton";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StandardCalculatorPom" /> class.
|
||||
/// </summary>
|
||||
/// <param name="uiObject">The UIObject that is the root of the standard calculator.</param>
|
||||
public StandardCalculatorPom(UIObject uiObject) : base(uiObject)
|
||||
{
|
||||
}
|
||||
|
||||
public NumberPadPom NumPad => new NumberPadPom(this.Descendants.Find(NumberPadId));
|
||||
|
||||
public MemoryPom MemoryControls => new MemoryPom(this);
|
||||
|
||||
public HistoryPom HistoryControls => new HistoryPom(this);
|
||||
|
||||
public UIObject StandardOperatorsGroup => this.Descendants.Find(StandardOperatorsId);
|
||||
|
||||
public UIObject DisplayControlsGroup => this.Descendants.Find(DisplayControlsId);
|
||||
|
||||
public Button EqualButton => new Button(this.StandardOperatorsGroup.Children.Find(EqualButtonId));
|
||||
|
||||
public Button ClearButton => new Button(this.DisplayControlsGroup.Children.Find(ClearButtonId));
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
public class UnitConverterLfm
|
||||
{
|
||||
public UnitConverterLfm(UnitConverterPom unitConverterPom)
|
||||
{
|
||||
this.ObjectModel = unitConverterPom;
|
||||
}
|
||||
|
||||
public UnitConverterPom ObjectModel { get; }
|
||||
|
||||
public void Eight()
|
||||
{
|
||||
using (var waiter = this.ObjectModel.GetDisplayChangedWaiter())
|
||||
{
|
||||
this.ObjectModel.NumberPad.EightButton.Invoke();
|
||||
waiter.TryWait();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using MS.Internal.Mita.Foundation;
|
||||
using MS.Internal.Mita.Foundation.Controls;
|
||||
using MS.Internal.Mita.Foundation.Waiters;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
public class UnitConverterPom : UIObject
|
||||
{
|
||||
private const string DisplayId = "Value1";
|
||||
private const string NumberPadId = "numberPad";
|
||||
|
||||
public UnitConverterPom(UIObject uiObject) : base(uiObject)
|
||||
{
|
||||
}
|
||||
|
||||
public NumberPadPom NumberPad => new NumberPadPom(this.Descendants.Find(NumberPadId));
|
||||
|
||||
public TextBlock Display => new TextBlock(this.Descendants.Find(DisplayId));
|
||||
|
||||
public PropertyChangedEventWaiter GetDisplayChangedWaiter() => this.Display.GetNameChangedWaiter();
|
||||
|
||||
public ElementAddedWaiter GetDisplayElementAddedWaiter() => new ElementAddedWaiter(this, Scope.Descendants, DisplayId);
|
||||
}
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Etw.Managed;
|
||||
using MS.Internal.Mita.Foundation;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
public class HistoryLfm : ICanFocusWithClicks
|
||||
{
|
||||
public HistoryLfm(HistoryPom historyPom)
|
||||
{
|
||||
this.ObjectModel = historyPom;
|
||||
}
|
||||
|
||||
public HistoryPom ObjectModel { get; }
|
||||
|
||||
public void FocusWithClicks()
|
||||
{
|
||||
// On the Programming calc, the default click location can land on the first memory item, dismissing the flyout.
|
||||
// Instead, click just below, in the gutter to the left of the trash can.
|
||||
var body = this.ObjectModel.Body;
|
||||
int height = body.BoundingRectangle.Height;
|
||||
body.DoubleClick(PointerButtons.Primary, Constants.ClickMargin, height + Constants.ClickMargin);
|
||||
}
|
||||
|
||||
public void OpenBody()
|
||||
{
|
||||
using (EtwWaiter waiter = new EtwWaiter(Constants.CalculatorETWProviderGUID, Constants.HistoryBodyOpenedETWEventName))
|
||||
{
|
||||
// Only one exists at a given time.
|
||||
if (this.ObjectModel.IsHistoryButtonVisible)
|
||||
{
|
||||
if (!this.ObjectModel.IsBodyOpen)
|
||||
{
|
||||
this.ObjectModel.HistoryButton.Invoke();
|
||||
waiter.Wait();
|
||||
}
|
||||
}
|
||||
else if (!this.ObjectModel.HistoryPivot.IsSelected)
|
||||
{
|
||||
this.ObjectModel.HistoryPivot.Click();
|
||||
waiter.Wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using MS.Internal.Mita.Foundation;
|
||||
using MS.Internal.Mita.Foundation.Controls;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
public class HistoryPom : UIObject
|
||||
{
|
||||
private const string HistoryButtonId = "HistoryButton";
|
||||
private const string HistoryPivotId = "HistoryLabel";
|
||||
private const string BodyId = "HistoryListView";
|
||||
|
||||
public HistoryPom(UIObject uiObject) : base(uiObject)
|
||||
{
|
||||
}
|
||||
|
||||
public Button HistoryButton => new Button(this.Descendants.Find(HistoryButtonId));
|
||||
|
||||
public bool IsHistoryButtonVisible => this.DoesDescendantExist(HistoryButtonId);
|
||||
|
||||
public TabItem HistoryPivot => new TabItem(this.Descendants.Find(HistoryPivotId));
|
||||
|
||||
public UIObject Body => this.Descendants.Find(BodyId);
|
||||
|
||||
public bool IsBodyOpen => this.DoesDescendantExist(BodyId);
|
||||
}
|
||||
}
|
@@ -0,0 +1,15 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
public interface ICanFocusWithClicks
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets focus on an object by clicking on it, without causing further action.
|
||||
/// Supports AccSpot scans by raising click events.
|
||||
/// </summary>
|
||||
void FocusWithClicks();
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using Etw.Managed;
|
||||
using MS.Internal.Mita.Foundation;
|
||||
using MS.Internal.Mita.Foundation.Waiters;
|
||||
using WEX.Logging.Interop;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
public class MemoryLfm : ICanFocusWithClicks
|
||||
{
|
||||
public MemoryLfm(MemoryPom memoryPom)
|
||||
{
|
||||
this.ObjectModel = memoryPom;
|
||||
}
|
||||
|
||||
public MemoryPom ObjectModel { get; }
|
||||
|
||||
public void FocusWithClicks()
|
||||
{
|
||||
// On the Programming calc, the default click location can land on the first memory item, dismissing the flyout.
|
||||
// Instead, click just below, in the gutter to the left of the trash can.
|
||||
var body = this.ObjectModel.Body;
|
||||
int height = body.BoundingRectangle.Height;
|
||||
body.DoubleClick(PointerButtons.Primary, Constants.ClickMargin, height + Constants.ClickMargin);
|
||||
}
|
||||
|
||||
public void OpenBody()
|
||||
{
|
||||
using (EtwWaiter waiter = new EtwWaiter(Constants.CalculatorETWProviderGUID, Constants.MemoryBodyOpenedETWEventName))
|
||||
{
|
||||
// Only one exists at a given time
|
||||
if (this.ObjectModel.IsMemoryButtonVisible)
|
||||
{
|
||||
if (!this.ObjectModel.IsBodyOpen)
|
||||
{
|
||||
this.ObjectModel.MemoryButton.Invoke();
|
||||
waiter.Wait();
|
||||
}
|
||||
}
|
||||
else if (!this.ObjectModel.MemoryPivot.IsSelected)
|
||||
{
|
||||
this.ObjectModel.MemoryPivot.Click();
|
||||
waiter.Wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using MS.Internal.Mita.Foundation;
|
||||
using MS.Internal.Mita.Foundation.Controls;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
public class MemoryPom : UIObject
|
||||
{
|
||||
private const string ClearMemoryButtonId = "ClearMemoryButton";
|
||||
private const string RecallButtonId = "MemRecall";
|
||||
private const string PlusButtonId = "MemPlus";
|
||||
private const string MinusButtonId = "MemMinus";
|
||||
private const string SetButtonId = "memButton";
|
||||
private const string MemoryButtonId = "MemoryButton";
|
||||
private const string MemoryPivotId = "MemoryLabel";
|
||||
private const string BodyId = "MemoryListView";
|
||||
|
||||
public MemoryPom(UIObject uiObject) : base(uiObject)
|
||||
{
|
||||
}
|
||||
|
||||
public Button ClearButton => new Button(this.Descendants.Find(ClearMemoryButtonId));
|
||||
|
||||
public Button RecallButton => new Button(this.Descendants.Find(RecallButtonId));
|
||||
|
||||
public Button PlusButton => new Button(this.Descendants.Find(PlusButtonId));
|
||||
|
||||
public Button MinusButton => new Button(this.Descendants.Find(MinusButtonId));
|
||||
|
||||
public Button SetButton => new Button(this.Descendants.Find(SetButtonId));
|
||||
|
||||
public Button MemoryButton => new Button(this.Descendants.Find(MemoryButtonId));
|
||||
|
||||
public bool IsMemoryButtonVisible => this.DoesDescendantExist(MemoryButtonId);
|
||||
|
||||
public TabItem MemoryPivot => new TabItem(this.Descendants.Find(MemoryPivotId));
|
||||
|
||||
public UIObject Body => this.Descendants.Find(BodyId);
|
||||
|
||||
public bool IsBodyOpen => this.DoesDescendantExist(BodyId);
|
||||
}
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using MS.Internal.Mita.Foundation;
|
||||
using MS.Internal.Mita.Foundation.Controls;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Components
|
||||
{
|
||||
public class NumberPadPom : UIObject
|
||||
{
|
||||
private const string OneButtonId = "num1Button";
|
||||
private const string TwoButtonId = "num2Button";
|
||||
private const string ThreeButtonId = "num3Button";
|
||||
private const string FourButtonId = "num4Button";
|
||||
private const string FiveButtonId = "num5Button";
|
||||
private const string SixButtonId = "num6Button";
|
||||
private const string SevenButtonId = "num7Button";
|
||||
private const string EightButtonId = "num8Button";
|
||||
private const string NineButtonId = "num9Button";
|
||||
private const string ZeroButtonId = "num0Button";
|
||||
private const string DecimalButtonId = "decimalSeparatorButton";
|
||||
|
||||
public NumberPadPom(UIObject uiObject) : base(uiObject)
|
||||
{
|
||||
}
|
||||
|
||||
public Button ZeroButton => new Button(this.Children.Find(ZeroButtonId));
|
||||
|
||||
public Button OneButton => new Button(this.Children.Find(OneButtonId));
|
||||
|
||||
public Button TwoButton => new Button(this.Children.Find(TwoButtonId));
|
||||
|
||||
public Button ThreeButton => new Button(this.Children.Find(ThreeButtonId));
|
||||
|
||||
public Button FourButton => new Button(this.Children.Find(FourButtonId));
|
||||
|
||||
public Button FiveButton => new Button(this.Children.Find(FiveButtonId));
|
||||
|
||||
public Button SixButton => new Button(this.Children.Find(SixButtonId));
|
||||
|
||||
public Button SevenButton => new Button(this.Children.Find(SevenButtonId));
|
||||
|
||||
public Button EightButton => new Button(this.Children.Find(EightButtonId));
|
||||
|
||||
public Button NineButton => new Button(this.Children.Find(NineButtonId));
|
||||
|
||||
public Button DecimalButton => new Button(this.Children.Find(DecimalButtonId));
|
||||
}
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Calculator.UIAutomationLibrary")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("D6913DAD-1C3B-4229-915F-8301A57970FC")]
|
||||
|
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Etw.Managed;
|
||||
using Calculator.UIAutomationLibrary.Components;
|
||||
using WEX.TestExecution;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Tests
|
||||
{
|
||||
public static class BasicCalculationTest
|
||||
{
|
||||
/// <summary>
|
||||
/// This test uses LFMs to add and then delete an alarm.
|
||||
/// </summary>
|
||||
/// <param name="calculatorAppLfm">The LFM for the alarms app window.</param>
|
||||
public static void CalculateOnePlusTwo(this CalculatorAppLfm calculatorAppLfm)
|
||||
{
|
||||
var mainPage = calculatorAppLfm.MainPageLfm;
|
||||
|
||||
var standardCalculator = mainPage.NavigateToStandardCalculator();
|
||||
|
||||
standardCalculator.OnePlusTwoEnter();
|
||||
|
||||
Verify.AreEqual("\u202D3\u202C", standardCalculator.ObjectModel.Display.Name, "Ensure display value is 3");
|
||||
|
||||
standardCalculator.Clear();
|
||||
|
||||
Verify.AreEqual("\u202D0\u202C", standardCalculator.ObjectModel.Display.Name, "Ensure display value is 0");
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Calculator.UIAutomationLibrary.Components;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using WEX.TestExecution;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary.Tests
|
||||
{
|
||||
public static class ScientificCalculationTest
|
||||
{
|
||||
/// <summary>
|
||||
/// This test uses LFMs to calculate the sqrt(4) - 2.
|
||||
/// </summary>
|
||||
/// <param name="calculatorAppLfm">The LFM for the calculator app window.</param>
|
||||
public static void CalculateSqrt4Minus2(this CalculatorAppLfm calculatorAppLfm)
|
||||
{
|
||||
var mainPage = calculatorAppLfm.MainPageLfm;
|
||||
|
||||
var scientificCalculator = mainPage.NavigateToScientificCalculator();
|
||||
|
||||
scientificCalculator.Press4();
|
||||
scientificCalculator.PressSqrt();
|
||||
scientificCalculator.PressMinus();
|
||||
scientificCalculator.Press3();
|
||||
scientificCalculator.PressPlus();
|
||||
scientificCalculator.Press1();
|
||||
scientificCalculator.PressEquals();
|
||||
|
||||
Verify.AreEqual("\u202D0\u202C", scientificCalculator.ObjectModel.Display.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
100
internal/Calculator.UIAutomationLibrary/Utilities/Constants.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary
|
||||
{
|
||||
public class Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// The path to the certificate file.
|
||||
/// </summary>
|
||||
public const string CertificateFileName = @"Calculator.cer";
|
||||
|
||||
/// <summary>
|
||||
/// The path to the appxbundle file.
|
||||
/// </summary>
|
||||
public const string PackageFileName = @"Calculator.appxbundle";
|
||||
|
||||
/// <summary>
|
||||
/// The path to the appxbundle file.
|
||||
/// </summary>
|
||||
public const string VCLibsPackageFileName = @"Microsoft.VCLibs.appx";
|
||||
|
||||
/// <summary>
|
||||
/// The path to the appxbundle file.
|
||||
/// </summary>
|
||||
public const string WinUIPackageFileName = @"Microsoft.UI.Xaml.appx";
|
||||
|
||||
/// <summary>
|
||||
/// Name of the CoreWindow.
|
||||
/// </summary>
|
||||
public const string AppWindowName = "Calculator";
|
||||
|
||||
/// <summary>
|
||||
/// Name of the process executable.
|
||||
/// </summary>
|
||||
public const string ProcessName = "Calculator.exe";
|
||||
|
||||
/// <summary>
|
||||
/// The package name.
|
||||
/// </summary>
|
||||
public const string PackageName = "Microsoft.WindowsCalculator";
|
||||
|
||||
/// <summary>
|
||||
/// The package family name for the app to test.
|
||||
/// </summary>
|
||||
public const string PackageFamilyName = PackageName + "_8wekyb3d8bbwe";
|
||||
|
||||
/// <summary>
|
||||
/// The package App User Model Id.
|
||||
/// </summary>
|
||||
public const string PackageAppUserModelId = PackageFamilyName + "!App";
|
||||
|
||||
/// <summary>
|
||||
/// AutomationId for the top level UI element.
|
||||
/// </summary>
|
||||
public const string TopLevelWindowAutomationId = "CalculatorWindow";
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the first page is loaded.
|
||||
/// </summary>
|
||||
public const string AppLaunchEndETWEventName = "AppLaunchEnd";
|
||||
|
||||
/// <summary>
|
||||
/// App Provider GUID for ETW Events
|
||||
/// </summary>
|
||||
public static readonly Guid CalculatorETWProviderGUID = new Guid("0905CA09-610E-401E-B650-2F212980B9E0");
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when a calculator mode change is complete.
|
||||
/// </summary>
|
||||
public const string AppModeChangeEndETWEventName = "ModeChangeEnd";
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the History panel is opened by flyout or by changing pivot tabs.
|
||||
/// </summary>
|
||||
public const string HistoryBodyOpenedETWEventName = "HistoryBodyOpened";
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the Memory panel is opened by flyout or by changing pivot tabs.
|
||||
/// </summary>
|
||||
public const string MemoryBodyOpenedETWEventName = "MemoryBodyOpened";
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the About flyout control is loaded.
|
||||
/// </summary>
|
||||
public const string AboutFlyoutOpenedETWEventName = "AboutFlyoutOpened";
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the Nav Bar control is opened.
|
||||
/// </summary>
|
||||
public const string NavBarOpenedETWEventName = "NavBarOpened";
|
||||
|
||||
/// <summary>
|
||||
/// Margin used to click in the gutter beneath the History and Memory lists
|
||||
/// </summary>
|
||||
public const int ClickMargin = 10;
|
||||
}
|
||||
}
|
101
internal/Calculator.UIAutomationLibrary/Utilities/EtwHelper.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.OneCoreUap.Test.AppModel;
|
||||
using WEX.Logging.Interop;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary
|
||||
{
|
||||
public class EtwHelper
|
||||
{
|
||||
private static bool etwServiceWasInstalled = false;
|
||||
|
||||
/// <summary>
|
||||
/// Installs and starts the Etw.Service so that Tests may utilize Etw Waiters.
|
||||
/// Wex.Services.exe is part of TAEF.
|
||||
/// </summary>
|
||||
public static void InstallAndStartETWService()
|
||||
{
|
||||
etwServiceWasInstalled = ServiceHelper.IsInstalled("Etw.Service");
|
||||
if (!etwServiceWasInstalled)
|
||||
{
|
||||
string wexServices = Path.Combine(TAEFHelper.GetTestDeploymentDirectory(), "Wex.Services.exe");
|
||||
if (!File.Exists(wexServices))
|
||||
{
|
||||
throw new FileNotFoundException(wexServices);
|
||||
}
|
||||
|
||||
Log.Comment("Attempting to install Etw.Service...");
|
||||
var startInfo = new ProcessStartInfo();
|
||||
startInfo.FileName = wexServices;
|
||||
startInfo.Arguments = "/install:Etw.Service";
|
||||
|
||||
var process = new Process();
|
||||
process.StartInfo = startInfo;
|
||||
if (process.Start())
|
||||
{
|
||||
process.WaitForExit();
|
||||
Log.Comment("Completed installation of Etw.Service");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("ETW service was not able to be installed. Process didn't start.");
|
||||
}
|
||||
}
|
||||
|
||||
Log.Comment("Attempting to start Etw.Service...");
|
||||
ServiceHelper.Start("Etw.Service");
|
||||
Log.Comment("Etw.Service started");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the Etw.Service.
|
||||
/// </summary>
|
||||
public static void StopAndRemoveETWService()
|
||||
{
|
||||
if (ServiceHelper.IsInstalled("Etw.Service"))
|
||||
{
|
||||
Log.Comment("Attempting to stop Etw.Service...");
|
||||
ServiceHelper.Stop("Etw.Service");
|
||||
Log.Comment("Etw.Service stopped");
|
||||
|
||||
// if we installed the Etw.Service as part of this test we should also remove it.
|
||||
// This prevents cases where TDP is upgraded but the service tregistration is referencing the old
|
||||
// location that no longer exists.
|
||||
if (!etwServiceWasInstalled)
|
||||
{
|
||||
|
||||
string wexServices = Path.Combine(TAEFHelper.GetTestDeploymentDirectory(), "Wex.Services.exe");
|
||||
if (!File.Exists(wexServices))
|
||||
{
|
||||
throw new FileNotFoundException(wexServices);
|
||||
}
|
||||
|
||||
Log.Comment("Attempting to remove Etw.Service...");
|
||||
var startInfo = new ProcessStartInfo();
|
||||
startInfo.FileName = wexServices;
|
||||
startInfo.Arguments = "/remove:Etw.Service";
|
||||
|
||||
var process = new Process();
|
||||
process.StartInfo = startInfo;
|
||||
if (process.Start())
|
||||
{
|
||||
process.WaitForExit();
|
||||
Log.Comment("Completed removal of Etw.Service");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("ETW service could not be removed. Process didn't start.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,100 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary
|
||||
{
|
||||
public static class Impersonater
|
||||
{
|
||||
public static void RunAs(RunAsUser user, Action action)
|
||||
{
|
||||
IntPtr errorInfo;
|
||||
SafeAccessTokenHandle restrictedToken;
|
||||
GetRunAsUserToken getRunAsUserToken = ResolveGetRunAsUserTokenMethod();
|
||||
Marshal.ThrowExceptionForHR(getRunAsUserToken(user, out restrictedToken, out errorInfo), errorInfo);
|
||||
|
||||
WindowsIdentity.RunImpersonated(restrictedToken, action);
|
||||
}
|
||||
|
||||
public static void RunAs<T>(RunAsUser user, Func<T> function)
|
||||
{
|
||||
IntPtr errorInfo;
|
||||
SafeAccessTokenHandle restrictedToken;
|
||||
GetRunAsUserToken getRunAsUserToken = ResolveGetRunAsUserTokenMethod();
|
||||
Marshal.ThrowExceptionForHR(getRunAsUserToken(user, out restrictedToken, out errorInfo), errorInfo);
|
||||
|
||||
WindowsIdentity.RunImpersonated(restrictedToken, function);
|
||||
}
|
||||
|
||||
// From: https://microsoft.visualstudio.com/EngSys/_git/validation.taef?path=%2Fsrc%2FTAEF%2FCommon%2FPublished%2FRunAsFromSystem.h&version=GBdevelop
|
||||
public enum RunAsUser
|
||||
{
|
||||
ElevatedUser,
|
||||
User,
|
||||
RestrictedUser,
|
||||
LowIL,
|
||||
InteractiveUser,
|
||||
};
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate int GetRunAsUserToken(RunAsUser user, out SafeAccessTokenHandle token, out IntPtr errorInfo);
|
||||
|
||||
// GetRunAsUserToken is defined in a namespace so we have to do some tricks to use P/Invoke.
|
||||
// We got the actual exported method name by running dumpbin /exports TE.Common.dll
|
||||
private static GetRunAsUserToken ResolveGetRunAsUserTokenMethod()
|
||||
{
|
||||
IntPtr teCommonDll = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
teCommonDll = LoadLibrary(@"TE.Common.dll");
|
||||
|
||||
IntPtr x64GetRunAsUserToken = GetProcAddress(teCommonDll, "?GetRunAsUserToken@TestExecution@WEX@@YAJW4RunAsUser@12@PEAPEAXPEAPEAUIErrorInfo@@@Z");
|
||||
if (x64GetRunAsUserToken != IntPtr.Zero)
|
||||
{
|
||||
return Marshal.GetDelegateForFunctionPointer<GetRunAsUserToken>(x64GetRunAsUserToken);
|
||||
}
|
||||
IntPtr x86GetRunAsUserToken = GetProcAddress(teCommonDll, "?GetRunAsUserToken@TestExecution@WEX@@YGJW4RunAsUser@12@PAPAXPAPAUIErrorInfo@@@Z");
|
||||
if (x86GetRunAsUserToken != IntPtr.Zero)
|
||||
{
|
||||
return Marshal.GetDelegateForFunctionPointer<GetRunAsUserToken>(x86GetRunAsUserToken);
|
||||
}
|
||||
IntPtr armGetRunAsUserToken = GetProcAddress(teCommonDll, "?GetRunAsUserToken@TestExecution@WEX@@YAJW4RunAsUser@12@PAPAXPAPAUIErrorInfo@@@Z");
|
||||
if (armGetRunAsUserToken != IntPtr.Zero)
|
||||
{
|
||||
return Marshal.GetDelegateForFunctionPointer<GetRunAsUserToken>(armGetRunAsUserToken);
|
||||
}
|
||||
IntPtr arm64GetRunAsUserToken = GetProcAddress(teCommonDll, "?GetRunAsUserToken@TestExecution@WEX@@YAJW4RunAsUser@12@PEAPEAXPEAPEAUIErrorInfo@@@Z");
|
||||
if (arm64GetRunAsUserToken != IntPtr.Zero)
|
||||
{
|
||||
return Marshal.GetDelegateForFunctionPointer<GetRunAsUserToken>(arm64GetRunAsUserToken);
|
||||
}
|
||||
|
||||
throw new Exception("Unable to find the GetRunAsUserToken function in DLL 'TE.Common.dll'");
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (teCommonDll != IntPtr.Zero)
|
||||
{
|
||||
FreeLibrary(teCommonDll);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern IntPtr LoadLibrary(string dllToLoad);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool FreeLibrary(IntPtr hModule);
|
||||
}
|
||||
}
|
@@ -0,0 +1,84 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading;
|
||||
using Microsoft.OneCoreUap.Test.AppModel;
|
||||
using WEX.Logging.Interop;
|
||||
using Windows.Foundation;
|
||||
using Windows.Management.Deployment;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary
|
||||
{
|
||||
public class InstallHelper
|
||||
{
|
||||
public static void InstallCertFile(string certFilePath)
|
||||
{
|
||||
// Ensure cert exists.
|
||||
if (!File.Exists(certFilePath))
|
||||
{
|
||||
throw new FileNotFoundException(certFilePath);
|
||||
}
|
||||
|
||||
// For some reason, attempting to use CertificateHelper.InstallFromSignedPackage() to install
|
||||
// the certificate associated with the appx package fails with the error:
|
||||
// "A certificate chain could not be built to a trusted root authority."
|
||||
// The reason is that the cert needs to be installed in 'StoreName.TrustedPeople',
|
||||
// but DeploymentHelper.AddPackage() attempts to install it in 'StoreName.Root'.
|
||||
// Therefore, the cert has been installed manually beforehand.
|
||||
Log.Comment($"Starting install of certificate at {certFilePath}");
|
||||
|
||||
X509Certificate2 certificate = new X509Certificate2(certFilePath);
|
||||
X509Store trustedPeopleStore = new X509Store(StoreName.TrustedPeople, StoreLocation.LocalMachine);
|
||||
trustedPeopleStore.Open(OpenFlags.MaxAllowed);
|
||||
trustedPeopleStore.Add(certificate);
|
||||
|
||||
Log.Comment($"Completed install of certificate");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Upgrades the appx/appxbundle from the path if needed.
|
||||
/// </summary>
|
||||
public static void InstallPackage(string appxFilePath, params string[] dependencyAppxFilePaths)
|
||||
{
|
||||
// Ensure the files exist.
|
||||
if (!File.Exists(appxFilePath))
|
||||
{
|
||||
throw new FileNotFoundException(appxFilePath);
|
||||
}
|
||||
foreach (var path in dependencyAppxFilePaths.Where(p => !File.Exists(p)))
|
||||
{
|
||||
throw new FileNotFoundException(path);
|
||||
}
|
||||
|
||||
Log.Comment($"Starting install of app package at {appxFilePath}");
|
||||
|
||||
PackageManager packageManager = new PackageManager();
|
||||
var deploymentOperation = packageManager.AddPackageAsync(
|
||||
new Uri(appxFilePath),
|
||||
dependencyAppxFilePaths.Select(d => new Uri(d)),
|
||||
DeploymentOptions.ForceApplicationShutdown | DeploymentOptions.ForceTargetApplicationShutdown | DeploymentOptions.ForceUpdateFromAnyVersion);
|
||||
|
||||
WaitForDeploymentOperation(deploymentOperation);
|
||||
|
||||
Log.Comment("Completed install of app package");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Waits for a deployment operation to complete
|
||||
/// </summary>
|
||||
private static void WaitForDeploymentOperation(IAsyncOperationWithProgress<DeploymentResult, DeploymentProgress> operation)
|
||||
{
|
||||
ManualResetEvent isCompletedEvent = new ManualResetEvent(false);
|
||||
operation.Completed = (IAsyncOperationWithProgress<DeploymentResult, DeploymentProgress> asyncInfo, AsyncStatus asyncStatus) =>
|
||||
{
|
||||
isCompletedEvent.Set();
|
||||
};
|
||||
|
||||
isCompletedEvent.WaitOne();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,139 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary
|
||||
{
|
||||
internal static class NativeMethods
|
||||
{
|
||||
internal const int GW_OWNER = 4;
|
||||
|
||||
internal delegate bool EnumThreadWindowsCallback(IntPtr hWnd, IntPtr lParam);
|
||||
|
||||
[DllImport("api-ms-win-ntuser-ie-window-l1-1-0.dll", SetLastError = true)]
|
||||
internal static extern bool EnumWindows(EnumThreadWindowsCallback callback, IntPtr extraData);
|
||||
|
||||
[DllImport("api-ms-win-ntuser-ie-window-l1-1-0.dll", SetLastError = true)]
|
||||
internal static extern int GetWindowThreadProcessId(IntPtr handle, out int processId);
|
||||
|
||||
[DllImport("api-ms-win-ntuser-ie-window-l1-1-0.dll", SetLastError = true)]
|
||||
internal static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
|
||||
|
||||
[DllImport("api-ms-win-ntuser-ie-window-l1-1-0.dll", SetLastError = true)]
|
||||
internal static extern int GetWindowTextLength(IntPtr hWnd);
|
||||
|
||||
[DllImport("api-ms-win-ntuser-ie-window-l1-1-0.dll", SetLastError = true)]
|
||||
internal static extern bool IsWindowVisible(IntPtr hWnd);
|
||||
|
||||
[DllImport("api-ms-win-ntuser-ie-window-l1-1-0.dll", SetLastError = true)]
|
||||
internal static extern int GetWindowLong(IntPtr hWnd, int nIndex);
|
||||
|
||||
[DllImport("api-ms-win-ntuser-ie-window-l1-1-0.dll", SetLastError = true)]
|
||||
internal static extern IntPtr GetWindow(IntPtr hWnd, int uCmd);
|
||||
|
||||
[DllImport("api-ms-win-ntuser-ie-window-l1-1-0.dll", SetLastError = true)]
|
||||
internal static extern bool SetForegroundWindow(IntPtr hWnd);
|
||||
|
||||
[DllImport("api-ms-win-service-management-l1-1-0.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool StartService(IntPtr hService, int dwNumServiceArgs, string[] lpServiceArgVectors);
|
||||
|
||||
[DllImport("api-ms-win-service-management-l1-1-0.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool ControlService(IntPtr hService, SERVICE_CONTROL dwControl, ref SERVICE_STATUS lpServiceStatus);
|
||||
|
||||
[DllImport("api-ms-win-service-management-l1-1-0.dll")]
|
||||
internal static extern IntPtr OpenSCManager(string machineName, string databaseName, uint dwAccess);
|
||||
|
||||
[DllImport("api-ms-win-service-management-l1-1-0.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool CloseServiceHandle(IntPtr hSCObject);
|
||||
|
||||
[DllImport("api-ms-win-service-management-l1-1-0.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
internal static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess);
|
||||
|
||||
[DllImport("api-ms-win-service-management-l1-1-0.dll", SetLastError = true)]
|
||||
internal static extern bool QueryServiceStatus(IntPtr hService, ref SERVICE_STATUS dwServiceStatus);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
internal struct SERVICE_STATUS
|
||||
{
|
||||
public int dwServiceType;
|
||||
public int dwCurrentState;
|
||||
public int dwControlsAccepted;
|
||||
public int dwWin32ExitCode;
|
||||
public int dwServiceSpecificExitCode;
|
||||
public int dwCheckPoint;
|
||||
public int dwWaitHint;
|
||||
}
|
||||
|
||||
internal static uint STANDARD_RIGHTS_REQUIRED = 0xF0000;
|
||||
|
||||
internal static uint SC_MANAGER_CONNECT = 0x0001;
|
||||
internal static uint SC_MANAGER_CREATE_SERVICE = 0x0002;
|
||||
internal static uint SC_MANAGER_ENUMERATE_SERVICE = 0x0004;
|
||||
internal static uint SC_MANAGER_LOCK = 0x0008;
|
||||
internal static uint SC_MANAGER_QUERY_LOCK_STATUS = 0x0010;
|
||||
internal static uint SC_MANAGER_MODIFY_BOOT_CONFIG = 0x0020;
|
||||
internal static uint SC_MANAGER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED |
|
||||
SC_MANAGER_CONNECT |
|
||||
SC_MANAGER_CREATE_SERVICE |
|
||||
SC_MANAGER_ENUMERATE_SERVICE |
|
||||
SC_MANAGER_LOCK |
|
||||
SC_MANAGER_QUERY_LOCK_STATUS |
|
||||
SC_MANAGER_MODIFY_BOOT_CONFIG);
|
||||
|
||||
internal static uint SERVICE_QUERY_CONFIG = 0x0001;
|
||||
internal static uint SERVICE_CHANGE_CONFIG = 0x0002;
|
||||
internal static uint SERVICE_QUERY_STATUS = 0x0004;
|
||||
internal static uint SERVICE_ENUMERATE_DEPENDENTS = 0x0008;
|
||||
internal static uint SERVICE_START = 0x0010;
|
||||
internal static uint SERVICE_STOP = 0x0020;
|
||||
internal static uint SERVICE_PAUSE_CONTINUE = 0x0040;
|
||||
internal static uint SERVICE_INTERROGATE = 0x0080;
|
||||
internal static uint SERVICE_USER_DEFINED_CONTROL = 0x0100;
|
||||
internal static uint SERVICE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED |
|
||||
SERVICE_QUERY_CONFIG |
|
||||
SERVICE_CHANGE_CONFIG |
|
||||
SERVICE_QUERY_STATUS |
|
||||
SERVICE_ENUMERATE_DEPENDENTS |
|
||||
SERVICE_START |
|
||||
SERVICE_STOP |
|
||||
SERVICE_PAUSE_CONTINUE |
|
||||
SERVICE_INTERROGATE |
|
||||
SERVICE_USER_DEFINED_CONTROL);
|
||||
|
||||
[Flags]
|
||||
internal enum SERVICE_CONTROL : uint
|
||||
{
|
||||
STOP = 0x00000001,
|
||||
PAUSE = 0x00000002,
|
||||
CONTINUE = 0x00000003,
|
||||
INTERROGATE = 0x00000004,
|
||||
SHUTDOWN = 0x00000005,
|
||||
PARAMCHANGE = 0x00000006,
|
||||
NETBINDADD = 0x00000007,
|
||||
NETBINDREMOVE = 0x00000008,
|
||||
NETBINDENABLE = 0x00000009,
|
||||
NETBINDDISABLE = 0x0000000A,
|
||||
DEVICEEVENT = 0x0000000B,
|
||||
HARDWAREPROFILECHANGE = 0x0000000C,
|
||||
POWEREVENT = 0x0000000D,
|
||||
SESSIONCHANGE = 0x0000000E
|
||||
}
|
||||
|
||||
internal enum SERVICE_STATE : int
|
||||
{
|
||||
SERVICE_STOPPED = 0x00000001,
|
||||
SERVICE_START_PENDING = 0x00000002,
|
||||
SERVICE_STOP_PENDING = 0x00000003,
|
||||
SERVICE_RUNNING = 0x00000004,
|
||||
SERVICE_CONTINUE_PENDING = 0x00000005,
|
||||
SERVICE_PAUSE_PENDING = 0x00000006,
|
||||
SERVICE_PAUSED = 0x00000007
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary
|
||||
{
|
||||
public class PerfConstants
|
||||
{
|
||||
/// <summary>
|
||||
/// Path where the regions, wprprofiles and wpaprofiles will be deployed to by the spkg.
|
||||
/// </summary>
|
||||
public const string ConfigDirectory = @"Config\";
|
||||
|
||||
/// <summary>
|
||||
/// Our FunGates source, where we can view test results.
|
||||
/// </summary>
|
||||
public const string FunGatesSource =
|
||||
#if DEBUG
|
||||
"TestSite";
|
||||
#else
|
||||
"Utility Apps Performance Tests";
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// The Windows Performance Recorder profile. These strings must have the config directory prefix.
|
||||
/// For use with the WPRProfileFile test attribute.
|
||||
/// </summary>
|
||||
public const string AppLifecycleWPRProfile = ConfigDirectory + "AppLifecycle.Profile.wprp";
|
||||
|
||||
/// <summary>
|
||||
/// The regions of interest file that contains the events we are interested in measuring.
|
||||
/// </summary>
|
||||
public const string AppLifecycleRegions = ConfigDirectory + "AppLifecycle.regions.xml";
|
||||
|
||||
/// <summary>
|
||||
/// These are uses with the DataSource test property to specify iteration info.
|
||||
/// </summary>
|
||||
public const string AppLifecycleInterationsSource = "Table:" + ConfigDirectory + "AppLifecycle.Iterations.xml#PerformanceConfigurations";
|
||||
}
|
||||
}
|
@@ -0,0 +1,156 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary
|
||||
{
|
||||
public class ServiceHelper
|
||||
{
|
||||
public static void Start(string serviceName, int timeoutInMilliSeconds = 30000)
|
||||
{
|
||||
IntPtr hService = IntPtr.Zero;
|
||||
IntPtr hSCManager = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
hSCManager = NativeMethods.OpenSCManager(null, null, NativeMethods.SC_MANAGER_ALL_ACCESS);
|
||||
if (IntPtr.Zero == hSCManager)
|
||||
{
|
||||
throw new Exception($"Start: Cannot Open OpenSCManager, {Marshal.GetLastWin32Error()}");
|
||||
}
|
||||
|
||||
hService = NativeMethods.OpenService(hSCManager, serviceName, NativeMethods.SERVICE_ALL_ACCESS);
|
||||
if (IntPtr.Zero == hService)
|
||||
{
|
||||
throw new Exception($"Start: Cannot Open Service, {Marshal.GetLastWin32Error()}");
|
||||
}
|
||||
|
||||
NativeMethods.SERVICE_STATUS serviceStatus = new NativeMethods.SERVICE_STATUS();
|
||||
if (!NativeMethods.QueryServiceStatus(hService, ref serviceStatus))
|
||||
{
|
||||
throw new Exception($"Start: Unable to query status of Service, {Marshal.GetLastWin32Error()}");
|
||||
}
|
||||
|
||||
if (serviceStatus.dwCurrentState != (int)NativeMethods.SERVICE_STATE.SERVICE_RUNNING &&
|
||||
serviceStatus.dwCurrentState != (int)NativeMethods.SERVICE_STATE.SERVICE_START_PENDING)
|
||||
{
|
||||
if (!NativeMethods.StartService(hService, 0, null))
|
||||
{
|
||||
throw new Exception($"Start: Service cannot be started, {Marshal.GetLastWin32Error()}");
|
||||
}
|
||||
}
|
||||
|
||||
WaitForStatus(hService, NativeMethods.SERVICE_STATE.SERVICE_RUNNING, TimeSpan.FromMilliseconds(timeoutInMilliSeconds));
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (IntPtr.Zero != hService)
|
||||
{
|
||||
NativeMethods.CloseServiceHandle(hService);
|
||||
}
|
||||
if (IntPtr.Zero != hSCManager)
|
||||
{
|
||||
NativeMethods.CloseServiceHandle(hSCManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Stop(string serviceName, int timeoutInMilliSeconds = 30000)
|
||||
{
|
||||
IntPtr hSCManager = IntPtr.Zero;
|
||||
IntPtr hService = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
hSCManager = NativeMethods.OpenSCManager(null, null, NativeMethods.SC_MANAGER_ALL_ACCESS);
|
||||
if (IntPtr.Zero == hSCManager)
|
||||
{
|
||||
throw new Exception($"Stop: Cannot Open OpenSCManager, {Marshal.GetLastWin32Error()}");
|
||||
}
|
||||
|
||||
hService = NativeMethods.OpenService(hSCManager, serviceName, NativeMethods.SERVICE_ALL_ACCESS);
|
||||
if (IntPtr.Zero == hService)
|
||||
{
|
||||
throw new Exception($"Stop: Cannot Open Service, {Marshal.GetLastWin32Error()}");
|
||||
}
|
||||
|
||||
NativeMethods.SERVICE_STATUS serviceStatus = new NativeMethods.SERVICE_STATUS();
|
||||
if (!NativeMethods.QueryServiceStatus(hService, ref serviceStatus))
|
||||
{
|
||||
throw new Exception($"Stop: Unable to query status of Service, {Marshal.GetLastWin32Error()}");
|
||||
}
|
||||
|
||||
if (serviceStatus.dwCurrentState != (int)NativeMethods.SERVICE_STATE.SERVICE_STOPPED &&
|
||||
serviceStatus.dwCurrentState != (int)NativeMethods.SERVICE_STATE.SERVICE_STOP_PENDING)
|
||||
{
|
||||
if (!NativeMethods.ControlService(hService, NativeMethods.SERVICE_CONTROL.STOP, ref serviceStatus))
|
||||
{
|
||||
throw new Exception($"Stop: Service cannot be stopped, {Marshal.GetLastWin32Error()}");
|
||||
}
|
||||
}
|
||||
|
||||
WaitForStatus(hService, NativeMethods.SERVICE_STATE.SERVICE_STOPPED, TimeSpan.FromMilliseconds(timeoutInMilliSeconds));
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (IntPtr.Zero != hService)
|
||||
{
|
||||
NativeMethods.CloseServiceHandle(hService);
|
||||
}
|
||||
|
||||
if (IntPtr.Zero != hSCManager)
|
||||
{
|
||||
NativeMethods.CloseServiceHandle(hSCManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsInstalled(string svcName)
|
||||
{
|
||||
IntPtr sc_handle = NativeMethods.OpenSCManager(null, null, NativeMethods.SC_MANAGER_ALL_ACCESS);
|
||||
if (sc_handle == IntPtr.Zero)
|
||||
{
|
||||
throw new Exception($"IsInstalled: Cannot open service manager, {Marshal.GetLastWin32Error()}");
|
||||
}
|
||||
|
||||
bool bResult = false;
|
||||
IntPtr sv_handle = NativeMethods.OpenService(sc_handle, svcName, NativeMethods.SERVICE_QUERY_CONFIG);
|
||||
if (sv_handle.ToInt64() != 0)
|
||||
{
|
||||
bResult = true;
|
||||
NativeMethods.CloseServiceHandle(sv_handle);
|
||||
}
|
||||
NativeMethods.CloseServiceHandle(sc_handle);
|
||||
return bResult;
|
||||
}
|
||||
|
||||
private static void WaitForStatus(IntPtr hService, NativeMethods.SERVICE_STATE desiredStatus, TimeSpan timeout)
|
||||
{
|
||||
Stopwatch swLoop = new Stopwatch();
|
||||
swLoop.Start();
|
||||
|
||||
NativeMethods.SERVICE_STATUS serviceStatus = new NativeMethods.SERVICE_STATUS();
|
||||
|
||||
do
|
||||
{
|
||||
Thread.Sleep(500);
|
||||
if (!NativeMethods.QueryServiceStatus(hService, ref serviceStatus))
|
||||
{
|
||||
throw new Exception($"WaitForStatus: Unable to query status of service, {Marshal.GetLastWin32Error()}");
|
||||
}
|
||||
}
|
||||
while (serviceStatus.dwCurrentState != (int)desiredStatus && (swLoop.ElapsedMilliseconds <= timeout.TotalMilliseconds));
|
||||
|
||||
if (serviceStatus.dwCurrentState != (int)desiredStatus)
|
||||
{
|
||||
throw new Exception($"WaitForStatus: Service failed to reach desired state: {desiredStatus}, current state: {serviceStatus.dwCurrentState}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Linq;
|
||||
using System.Windows.Automation;
|
||||
using MS.Internal.Mita.Foundation;
|
||||
using MS.Internal.Mita.Foundation.Controls;
|
||||
using MS.Internal.Mita.Foundation.Waiters;
|
||||
using WEX.Logging.Interop;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary
|
||||
{
|
||||
public static class UIObjectExtensions
|
||||
{
|
||||
private const string NamePropertyName = "Name";
|
||||
private static UICondition CoreWindowCondition = UICondition.CreateFromClassName("Windows.UI.Core.CoreWindow");
|
||||
|
||||
public static Window GetParentCoreWindow(this UIObject uiObject)
|
||||
{
|
||||
if (uiObject.Matches(CoreWindowCondition))
|
||||
{
|
||||
return new Window(uiObject);
|
||||
}
|
||||
|
||||
return new Window(uiObject.Ancestors.Find(CoreWindowCondition));
|
||||
}
|
||||
|
||||
public static Window GetTopLevelWindow(this Window window)
|
||||
{
|
||||
var node = window;
|
||||
while (node != null && node.Parent != null && node.Parent.ControlType == ControlType.Window)
|
||||
{
|
||||
node = new Window(node.Parent);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
public static void VerifyParentTreeStructure(this UIObject uiObject)
|
||||
{
|
||||
var node = uiObject;
|
||||
while (node != null && node.Parent != null)
|
||||
{
|
||||
if (!node.Parent.Children.Contains(node))
|
||||
{
|
||||
Log.Comment($"- [VerifyingTree] {node} specifies {node.Parent} as parent but is not part of its children.");
|
||||
}
|
||||
if (!node.Parent.Descendants.Contains(node))
|
||||
{
|
||||
Log.Comment($"- [VerifyingTree] {node} specifies {node.Parent} as parent but is not part of its descendants.");
|
||||
}
|
||||
node = node.Parent;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool DoesDescendantExist(this UIObject uiObject, string automationId)
|
||||
{
|
||||
UIObject temp;
|
||||
return uiObject.Descendants.TryFind(automationId, out temp);
|
||||
}
|
||||
|
||||
public static PropertyChangedEventWaiter GetNameChangedWaiter(this TextBlock textBlock)
|
||||
{
|
||||
return new PropertyChangedEventWaiter(textBlock, UIProperty.Get(NamePropertyName));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using WEX.Logging.Interop;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary
|
||||
{
|
||||
public class Utilities
|
||||
{
|
||||
public static void KillExistingCalculatorProcesses()
|
||||
{
|
||||
Log.Comment("Killing any existing Calculator processes");
|
||||
|
||||
foreach (var process in Process.GetProcessesByName(Path.GetFileNameWithoutExtension(Constants.ProcessName)))
|
||||
{
|
||||
try
|
||||
{
|
||||
process.Kill();
|
||||
Log.Comment($"Killed {process.ProcessName}, Id: {process.Id}");
|
||||
}
|
||||
catch (Exception) when (process.HasExited)
|
||||
{
|
||||
Log.Comment($"{process.ProcessName}, Id: {process.Id} already exited.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using MS.Internal.Mita.Foundation.Controls;
|
||||
using WEX.Logging.Interop;
|
||||
|
||||
namespace Calculator.UIAutomationLibrary
|
||||
{
|
||||
public class WindowHelper
|
||||
{
|
||||
public static void SetAsForeground(Window window)
|
||||
{
|
||||
Log.Comment($"Set window {window.NativeWindowHandle} as the foreground window.");
|
||||
|
||||
NativeMethods.SetForegroundWindow(window.NativeWindowHandle);
|
||||
}
|
||||
}
|
||||
}
|
12
internal/Calculator.UIAutomationLibrary/project.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"AppModel.TestHelper": "2018.3.22",
|
||||
"EtwProcessor.Managed": "10.34.181220007",
|
||||
"MITALite": "1.0.180128001",
|
||||
"Taef.Managed": "10.34.181220007",
|
||||
"Test.Net.Redist": "2.0.1"
|
||||
},
|
||||
"frameworks": {
|
||||
"netcore50": {}
|
||||
}
|
||||
}
|
145
internal/Calculator.UITests/Calculator.UITests.csproj
Normal file
@@ -0,0 +1,145 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<ProjectGuid>{0224A709-0C48-4C4F-BA17-843A49842C15}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Calculator.UITests</RootNamespace>
|
||||
<AssemblyName>Calculator.UITests</AssemblyName>
|
||||
<TargetFrameworkIdentifier>.NETPortable</TargetFrameworkIdentifier>
|
||||
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
|
||||
<NuGetTargetMoniker>.NETCore,Version=v5.0</NuGetTargetMoniker>
|
||||
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
||||
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.17763.0</TargetPlatformVersion>
|
||||
<TargetPlatformMinVersion>10.0.17134.0</TargetPlatformMinVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<CopyNuGetImplementations>true</CopyNuGetImplementations>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\x86</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\x86</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\x64</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\x64</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|ARM' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\arm</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>ARM</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|ARM' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\arm</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>ARM</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|ARM64' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\ARM64\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>ARM64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|ARM64' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\ARM64\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>ARM64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Initialization.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Tests\AppLifecycleTests.cs" />
|
||||
<Compile Include="Tests\CalculatorTests.cs" />
|
||||
<Compile Include="Tests\LaunchTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Config\AppLifecycle.Profile.wprp">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Config\AppLifecycle.Regions.tt">
|
||||
<Generator>TextTemplatingFileGenerator</Generator>
|
||||
<LastGenOutput>AppLifecycle.Regions.xml</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
<Content Include="Config\AppLifecycle.Regions.xml">
|
||||
<DependentUpon>AppLifecycle.Regions.tt</DependentUpon>
|
||||
<AutoGen>True</AutoGen>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Content>
|
||||
<None Include="project.json" />
|
||||
<None Include="testmd.definition" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Calculator.UIAutomationLibrary\Calculator.UIAutomationLibrary.csproj">
|
||||
<Project>{a43517b5-8be3-4312-913f-004978c34444}</Project>
|
||||
<Name>Calculator.UIAutomationLibrary</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Config\AppLifecycle.Iterations.xml">
|
||||
<SubType>Designer</SubType>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '15.0' ">
|
||||
<VisualStudioVersion>15.0</VisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!--
|
||||
This file defines a table of preformance configuration for use with
|
||||
TAEF Table Based Data-driven Testing.
|
||||
|
||||
This table specifies we will run the test three times (each iteration has a
|
||||
unique name to identify the scenario) with different parameters each time.
|
||||
We use the same region file for WinPerf but we specify different WPR profiles
|
||||
to capture ETW events from different providers, focusing on responsiveness for
|
||||
launch runs and on memory for one diagnostic memory run.
|
||||
|
||||
The warm run is the one we are primarily interested in for startup performance.
|
||||
-->
|
||||
|
||||
<Data>
|
||||
<Table Id="PerformanceConfigurations">
|
||||
<Row Name="Cold"
|
||||
WinPerf.FriendlyAutomationName="AppLifecycle_Responsiveness_Cold"
|
||||
WinPerf.Iterations="1"
|
||||
WinPerf.WPRProfile="Config\AppLifecycle.Profile.wprp"
|
||||
WinPerf.WPRProfileId="AppLifecycle.Responsiveness.Diagnostic.Verbose.File"
|
||||
WinPerf.Regions="Config\AppLifecycle.Regions.xml">
|
||||
</Row>
|
||||
<Row Name="Warm"
|
||||
WinPerf.FriendlyAutomationName="AppLifecycle_Responsiveness_Warm"
|
||||
WinPerf.Iterations="10"
|
||||
WinPerf.WPRProfile="Config\AppLifecycle.Profile.wprp"
|
||||
WinPerf.WPRProfileId="AppLifecycle.Responsiveness.Diagnostic.Verbose.Memory"
|
||||
WinPerf.Regions="Config\AppLifecycle.Regions.xml">
|
||||
</Row>
|
||||
<Row Name="Memory"
|
||||
WinPerf.FriendlyAutomationName="AppLifecycle_Memory"
|
||||
WinPerf.Iterations="1"
|
||||
WinPerf.WPRProfile="Config\AppLifecycle.Profile.wprp"
|
||||
WinPerf.WPRProfileId="AppLifecycle.Memory.Diagnostic.Verbose.File"
|
||||
WinPerf.Regions="Config\AppLifecycle.Regions.xml">
|
||||
</Row>
|
||||
</Table>
|
||||
</Data>
|
526
internal/Calculator.UITests/Config/AppLifecycle.Profile.wprp
Normal file
@@ -0,0 +1,526 @@
|
||||
<!--
|
||||
|
||||
This WPRP (WPR profile) contains the App Life Cycle settings for Mobile and Client Performance Gates (MPG and CPG).
|
||||
Since the appcycle automations are currently still separate, any changes here should be made in two places to keep these wprp's in sync.
|
||||
CPG: base\PerfTest\MemRe\AppLifecycle\Common\AppLifeCycle.wprp
|
||||
MPG: wm\src\tools\Product\DH\Test\PerfWorkloads\AppLifeCycle\AppLifeCycle.wprp
|
||||
|
||||
Prefixes in the WPRP:
|
||||
SC_ - System Collector controlling kernel event tracing
|
||||
EC_ - Event Collector controlling user mode event tracing
|
||||
|
||||
SP_ - System Provider
|
||||
|
||||
EP_ - Event Provider
|
||||
|
||||
There are two separate traces - Responsiveness and Memory.
|
||||
Within that, we have Light tracing which is for official gating metrics/traces, and we have Verbose tracing, which is for Diagnostic metrics\traces.
|
||||
|
||||
-->
|
||||
|
||||
<WindowsPerformanceRecorder Version="1.0" Comments="Test" Company="Microsoft Corporation" Copyright="Microsoft Corporation">
|
||||
<Profiles>
|
||||
<!-- BufferSizes are in KB in WPRP -->
|
||||
|
||||
<!-- System Collectors -->
|
||||
<SystemCollector Id="SC_Responsiveness.LowCost.Light" Name="NT Kernel Resposiveness Logger LowCost Light">
|
||||
<BufferSize Value="1024" />
|
||||
<Buffers Value="3" PercentageOfTotalMemory="true" MaximumBufferSpace="30" />
|
||||
</SystemCollector>
|
||||
|
||||
<SystemCollector Id="SC_Responsiveness.LowCost" Name="NT Kernel Resposiveness Logger LowCost">
|
||||
<BufferSize Value="1024" />
|
||||
<Buffers Value="35" />
|
||||
</SystemCollector>
|
||||
|
||||
<SystemCollector Id="SC_Responsiveness.HighCost.Verbose" Name="NT Kernel Resposiveness Logger HighCost Verbose">
|
||||
<BufferSize Value="1024" />
|
||||
<Buffers Value="7" PercentageOfTotalMemory="true" MaximumBufferSpace="140" />
|
||||
</SystemCollector>
|
||||
|
||||
<SystemCollector Id="SC_Memory.LowCost.Light" Name="NT Kernel Memory Logger LowCost Light">
|
||||
<BufferSize Value="1024" />
|
||||
<Buffers Value="35" />
|
||||
</SystemCollector>
|
||||
|
||||
<SystemCollector Id="SC_Memory.HighCost.Verbose" Name="NT Kernel Memory Logger LowCost Light">
|
||||
<BufferSize Value="1024" />
|
||||
<Buffers Value="75" />
|
||||
</SystemCollector>
|
||||
|
||||
<!-- Event Collectors -->
|
||||
<EventCollector Id="EC_Responsiveness.LowCost.Light" Name="User Session Logger LowCost Light">
|
||||
<BufferSize Value="1024" />
|
||||
<Buffers Value="2" PercentageOfTotalMemory="true" MaximumBufferSpace="20"/>
|
||||
</EventCollector>
|
||||
|
||||
<EventCollector Id="EC_Responsiveness.LowCost.Light.UTC" Name="User Session Logger LowCost Light UTC">
|
||||
<BufferSize Value="1024"/>
|
||||
<Buffers Value="5"/>
|
||||
</EventCollector>
|
||||
|
||||
<EventCollector Id="EC_Responsiveness.LowCost" Name="User Session Logger LowCost">
|
||||
<BufferSize Value="1024" />
|
||||
<Buffers Value="15" />
|
||||
</EventCollector>
|
||||
|
||||
<EventCollector Id="EC_Responsiveness.HighCost.Verbose" Name="User Session Logger Higcost Verbose">
|
||||
<BufferSize Value="1024" />
|
||||
<Buffers Value="3" PercentageOfTotalMemory="true" MaximumBufferSpace="60" />
|
||||
</EventCollector>
|
||||
|
||||
<EventCollector Id="EC_Memory.LowCost.Light" Name="User Session Logger LowCost Light">
|
||||
<BufferSize Value="1024" />
|
||||
<Buffers Value="30" />
|
||||
</EventCollector>
|
||||
|
||||
<!-- System Providers for collecting kernel events. -->
|
||||
<SystemProvider Id="SP_Responsiveness.Light">
|
||||
<Keywords Operation="Add">
|
||||
<Keyword Value="CompactCSwitch"/>
|
||||
<Keyword Value="CSwitch"/>
|
||||
<Keyword Value="DiskIO"/>
|
||||
<Keyword Value="ProcessThread"/>
|
||||
<Keyword Value="Loader"/>
|
||||
</Keywords>
|
||||
</SystemProvider>
|
||||
<SystemProvider Id="SP_Responsiveness" Base="SP_Responsiveness.Light">
|
||||
<Keywords Operation="Add">
|
||||
<Keyword Value="HardFaults"/>
|
||||
<Keyword Value="MemoryInfo"/>
|
||||
<Keyword Value="ReadyThread"/>
|
||||
<Keyword Value="SampledProfile"/>
|
||||
<Keyword Value="Session"/>
|
||||
<Keyword Value="VAMap"/>
|
||||
<Keyword Value="DPC"/>
|
||||
<Keyword Value="Power"/>
|
||||
</Keywords>
|
||||
<Stacks Operation="Add">
|
||||
<Stack Value="CSwitch"/>
|
||||
<Stack Value="ReadyThread"/>
|
||||
<Stack Value="SampledProfile"/>
|
||||
</Stacks>
|
||||
</SystemProvider>
|
||||
<SystemProvider Id="SP_Memory.Light" Base="SP_Responsiveness.Light" >
|
||||
<Keywords Operation="Add">
|
||||
<Keyword Value="Memory"/>
|
||||
<Keyword Value="MemoryInfo"/>
|
||||
<Keyword Value="HardFaults"/>
|
||||
<Keyword Value="ReferenceSet"/>
|
||||
<Keyword Value="VirtualAllocation"/>
|
||||
</Keywords>
|
||||
</SystemProvider>
|
||||
<SystemProvider Id="SP_Memory" Base="SP_Responsiveness" >
|
||||
<Keywords Operation="Add">
|
||||
<Keyword Value="FootPrint"/>
|
||||
<Keyword Value="Memory"/>
|
||||
<Keyword Value="MemoryInfoWS"/>
|
||||
<Keyword Value="ReferenceSet"/>
|
||||
<Keyword Value="VirtualAllocation"/>
|
||||
</Keywords>
|
||||
<Stacks Operation="Add">
|
||||
<Stack Value="HeapCreate" />
|
||||
<Stack Value="ImageLoad" />
|
||||
<Stack Value="PageAccess" />
|
||||
<Stack Value="PageAccessEx" />
|
||||
<Stack Value="PagefileMappedSectionCreate" />
|
||||
<Stack Value="PagefileMappedSectionDelete" />
|
||||
<Stack Value="PageRangeAccess" />
|
||||
<Stack Value="PageRangeRelease" />
|
||||
<Stack Value="PageRelease" />
|
||||
<Stack Value="PageRemovedfromWorkingSet" />
|
||||
<Stack Value="VirtualAllocation" />
|
||||
<Stack Value="VirtualFree" />
|
||||
</Stacks>
|
||||
</SystemProvider>
|
||||
<!-- Start - AppLaunch.wprp -->
|
||||
<EventProvider Id="EP_UTC" Name="UTC" NonPagedMemory="true" Level="4" />
|
||||
<EventProvider Id="EP_Microsoft-WindowsPhone-AppPlatProvider" Name="3C42000F-CC27-48C3-A005-48F6E38B131F" >
|
||||
<Keywords>
|
||||
<Keyword Value="0x0"/>
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_XNA" Name="CD698436-A3E3-4607-BB60-0BAC4D765B59" >
|
||||
<Keywords>
|
||||
<Keyword Value="0x0"/>
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_TaskHost" Name="5CBDF2A5-7290-4ACC-B8A7-9BA285BEBC39" >
|
||||
<Keywords>
|
||||
<Keyword Value="0x0"/>
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-WindowsPhone-Silverlight" Name="AA087E0E-0B35-4e28-8F3A-440C3F51EEF1" >
|
||||
<Keywords>
|
||||
<Keyword Value="0x0"/>
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Device-Health-Etw" Name="F7A8FD9F-8FFD-482f-86C0-4C19240F334C" >
|
||||
<Keywords>
|
||||
<Keyword Value="0x0"/>
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-WindowsMobile-Compositor" Name="85FFFBA1-CF12-402c-B9B3-29A3217BB007" Level="5">
|
||||
<Keywords>
|
||||
<Keyword Value="0xfffffff" />
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-WindowsMobile-Splash" Name="872c8950-0def-4d5b-83f6-57dd027f88ce" Level="4">
|
||||
<Keywords>
|
||||
<Keyword Value="0xfffffff" />
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-WindowsMobile-UIXMobile" Name="0C0FFEE0-F4B1-4F4D-B591-FB3175B13413">
|
||||
<Keywords>
|
||||
<Keyword Value="0xE" />
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-WindowsMobile-StartMenu" Name="BECF83FD-D220-4b19-B7C1-C9127307F6B1" Level="5">
|
||||
<Keywords>
|
||||
<Keyword Value="0xfffffff" />
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-Windows-Kernel-EventTracing" Name="b675ec37-bdb6-4648-bc92-f3fdc74d3ca2" Level="5">
|
||||
<Keywords>
|
||||
<Keyword Value="0x50" />
|
||||
</Keywords>
|
||||
<CaptureStateOnSave>
|
||||
<Keyword Value="0x50" />
|
||||
</CaptureStateOnSave>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-WindowsPhone-MobileUI" Name="F243DC34-205E-4d34-94CA-36E8C0859787" Level="5">
|
||||
<Keywords>
|
||||
<Keyword Value="0xfffffff" />
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-Windows-Kernel-Process" Name="2839ff94-8f12-4e1b-82e3-af7af77a450f" NonPagedMemory="true" >
|
||||
<Keywords>
|
||||
<Keyword Value="0x0"/>
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-Windows-TestExecution" Name="Microsoft-Windows-TestExecution" >
|
||||
<Keywords>
|
||||
<Keyword Value="0x0"/>
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft.Windows.WinPerf" Name="BE6F04EA-3488-4543-8082-24843EAEC303" >
|
||||
<Keywords>
|
||||
<Keyword Value="0x0"/>
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-Windows-Shell-Launcher" Name="*Microsoft-Windows-Shell-Launcher" >
|
||||
<Keywords>
|
||||
<Keyword Value="0x0"/>
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-Windows-Immersive-Shell" Name="315A8872-923E-4EA2-9889-33CD4754BF64" >
|
||||
<Keywords>
|
||||
<Keyword Value="0x0"/>
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-Windows-XAML-Light" Name="531A35AB-63CE-4BCF-AA98-F88C7A89E455" Level="4" >
|
||||
<Keywords>
|
||||
<Keyword Value="0x0"/>
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-Windows-XAML-Verbose" Name="531A35AB-63CE-4BCF-AA98-F88C7A89E455" Level="5" >
|
||||
<Keywords>
|
||||
<Keyword Value="0x0"/>
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-Windows-ProcessLifetimeManager" Name="*Microsoft.Windows.ProcessLifetimeManager" >
|
||||
<Keywords>
|
||||
<Keyword Value="0x0"/>
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-Windows-Desktop-ApplicationFrame" Name="678e492b-5de1-50c5-7219-ae4aa7d6a141" Level="5" >
|
||||
<Keywords>
|
||||
<Keyword Value="0x0"/>
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-Microsoft-Phone-AppLifecycle" Name="f623a8ef-84da-4640-8917-fd5b0f847f28" >
|
||||
<Keywords>
|
||||
<Keyword Value="0x0"/>
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-WindowsPhone-CoreUIComponents" Name="a0b7550f-4e9a-4f03-ad41-b8042d06a2f7" >
|
||||
<Keywords>
|
||||
<Keyword Value="0x0"/>
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-Windows-AppModel-Exec" Name="EB65A492-86C0-406A-BACE-9912D595BD69" >
|
||||
<Keywords>
|
||||
<Keyword Value="0x0"/>
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft.Windows.ActivationManager" Name="cf7f94b3-08dc-5257-422f-497d7dc86ab3">
|
||||
<Keywords>
|
||||
<Keyword Value="0x0" />
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-WindowsMobile-ExecManLogPublisher" Name="82c8ad90-5f3c-11be-bd9a-85bb5f50dfa4" >
|
||||
<Keywords>
|
||||
<Keyword Value="0x0"/>
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-Windows-Shell-CortanaSearch" Name="E34441D9-5BCF-4958-B787-3BF824F362D7" >
|
||||
<Keywords>
|
||||
<Keyword Value="0x0"/>
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-Windows-Dwm-Core" Name="9e9bba3c-2e38-40cb-99f4-9e8281425164" Level="4" >
|
||||
<Keywords>
|
||||
<Keyword Value="0x2000C"/>
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-Windows-ImageLoad" Name="2cb15d1d-5fc1-11d2-abe1-00a0c911f518" >
|
||||
<Keywords>
|
||||
<Keyword Value="0x10"/>
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-Windows-AppLifeCycle-UI" Name="ee97cdc4-b095-5c70-6e37-a541eb74c2b5" Level="5">
|
||||
<Keywords>
|
||||
<Keyword Value="0x400000000000"/>
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-Windows-AppLifeCycle" Name="ef00584a-2655-462c-bc24-e7de630e7fbf">
|
||||
<Keywords>
|
||||
<Keyword Value="0x0000000000000"/>
|
||||
</Keywords>
|
||||
<CaptureStateOnSave>
|
||||
<Keyword Value="0x0000000000000"/>
|
||||
</CaptureStateOnSave>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-Windows-Kernel-Power" Name="331C3B3A-2005-44C2-AC5E-77220C37D6B4" NonPagedMemory="true" EventKey="true">
|
||||
<Keywords>
|
||||
<Keyword Value="0xA4"/>
|
||||
</Keywords>
|
||||
<CaptureStateOnSave Timeout="0">
|
||||
<Keyword Value="0xA4"/>
|
||||
</CaptureStateOnSave>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-Windows-Kernel-Processor-Power" Name="0f67e49f-fe51-4e9f-b490-6f2948cc6027" NonPagedMemory="true" EventKey="true" Level="4">
|
||||
<Keywords>
|
||||
<Keyword Value="0xC2"/>
|
||||
</Keywords>
|
||||
<CaptureStateOnSave Timeout="0">
|
||||
<Keyword Value="0xC2"/>
|
||||
</CaptureStateOnSave>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-Windows-Kernel-Pep" Name="5412704E-B2E1-4624-8FFD-55777B8F7373" NonPagedMemory="true" EventKey="true">
|
||||
<Keywords>
|
||||
<Keyword Value="0x0"/>
|
||||
</Keywords>
|
||||
<CaptureStateOnSave Timeout="0">
|
||||
<Keyword Value="0x0"/>
|
||||
</CaptureStateOnSave>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-Windows-Kernel-Acpi" Name="C514638F-7723-485B-BCFC-96565D735D4A" Level="5" NonPagedMemory="true" EventKey="true">
|
||||
<Keywords>
|
||||
<Keyword Value="0x0"/>
|
||||
</Keywords>
|
||||
<CaptureStateOnSave>
|
||||
<Keyword Value="0x0"/>
|
||||
</CaptureStateOnSave>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-Windows-UserModePowerService" Name="CE8DEE0B-D539-4000-B0F8-77BED049C590" NonPagedMemory="true" EventKey="true">
|
||||
<Keywords>
|
||||
<Keyword Value="0x0"/>
|
||||
</Keywords>
|
||||
<CaptureStateOnSave Timeout="0">
|
||||
<Keyword Value="0x0"/>
|
||||
</CaptureStateOnSave>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft.ClipC" Level="0" Name="ed0c10a5-5396-4a96-9ee3-6f4aa0d1120d" NonPagedMemory="true" EventKey="true">
|
||||
<Keywords>
|
||||
<Keyword Value="0x200000000000" />
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft.ClipSp" Level="0" Name="b4b126de-32fe-4591-9ac5-b0778d79a0e7" NonPagedMemory="true" EventKey="true">
|
||||
<Keywords>
|
||||
<Keyword Value="0x200000000000" />
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft.ClipSvc" Level="0" Name="b94d76c5-9d56-454a-8d1b-6ca30898160e" NonPagedMemory="true" EventKey="true">
|
||||
<Keywords>
|
||||
<Keyword Value="0x200000000000" />
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft.Windows.LicenseManager.Telemetry" Level="0" Name="af9f58ec-0c04-4be9-9eb5-55ff6dbe72d7" NonPagedMemory="true" EventKey="true">
|
||||
<Keywords>
|
||||
<Keyword Value="0x200000000000" />
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-Windows-Win32k" Level="0" Name="8c416c79-d49b-4f01-a467-e56d3aa8234c" NonPagedMemory="true" EventKey="true">
|
||||
<Keywords>
|
||||
<Keyword Value="0x26A000" />
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<EventProvider Id="EP_Microsoft-Windows-Kernel-Prefetch" Level="0" Name="Microsoft-Windows-Kernel-Prefetch" NonPagedMemory="true" EventKey="true">
|
||||
<Keywords>
|
||||
<Keyword Value="0x0" />
|
||||
</Keywords>
|
||||
</EventProvider>
|
||||
<!-- End - AppLaunch.wprp -->
|
||||
<Profile Id="AppLifecycle.Responsiveness.Light.File" LoggingMode="File" Name="AppLifecycle.Responsiveness" DetailLevel="Light" Description="App lifecycle responsiveness light to file">
|
||||
<Collectors>
|
||||
<SystemCollectorId Value="SC_Responsiveness.LowCost.Light">
|
||||
<SystemProviderId Value="SP_Responsiveness.Light" />
|
||||
</SystemCollectorId>
|
||||
<EventCollectorId Value="EC_Responsiveness.LowCost.Light">
|
||||
<EventProviders>
|
||||
<EventProviderId Value="EP_Microsoft-Windows-TestExecution" />
|
||||
<EventProviderId Value="EP_Microsoft.Windows.WinPerf" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Immersive-Shell"/>
|
||||
<EventProviderId Value="EP_Microsoft-Windows-AppLifeCycle" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Shell-Launcher" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-XAML-Light" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-AppLifeCycle-UI" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Kernel-Process" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Shell-CortanaSearch"/>
|
||||
<EventProviderId Value="EP_Microsoft-Windows-AppModel-Exec"/>
|
||||
<EventProviderId Value="EP_Microsoft.Windows.ActivationManager" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Kernel-EventTracing" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Desktop-ApplicationFrame" />
|
||||
<EventProviderId Value="EP_XNA" />
|
||||
<EventProviderId Value="EP_TaskHost" />
|
||||
<EventProviderId Value="EP_Device-Health-Etw" />
|
||||
<EventProviderId Value="EP_Microsoft-Microsoft-Phone-AppLifecycle"/>
|
||||
<EventProviderId Value="EP_Microsoft-WindowsPhone-CoreUIComponents"/>
|
||||
<EventProviderId Value="EP_Microsoft-WindowsPhone-AppPlatProvider" />
|
||||
<EventProviderId Value="EP_Microsoft-WindowsPhone-Silverlight" />
|
||||
<EventProviderId Value="EP_Microsoft-WindowsMobile-Splash" />
|
||||
</EventProviders>
|
||||
</EventCollectorId>
|
||||
<EventCollectorId Value="EC_Responsiveness.LowCost.Light.UTC">
|
||||
<EventProviders>
|
||||
<EventProviderId Value="EP_UTC"/>
|
||||
</EventProviders>
|
||||
</EventCollectorId>
|
||||
</Collectors>
|
||||
</Profile>
|
||||
<Profile Id="AppLifecycle.Responsiveness.Diagnostic.Verbose.File" Base="AppLifecycle.Responsiveness.Light.File" LoggingMode="File" Name="AppLifecycle.Responsiveness.Diagnostic" DetailLevel="Verbose" Description="App lifecycle responsiveness verbose to file">
|
||||
<Collectors Operation="Add">
|
||||
<SystemCollectorId Value="SC_Responsiveness.LowCost">
|
||||
<SystemProviderId Value="SP_Responsiveness" />
|
||||
</SystemCollectorId>
|
||||
<EventCollectorId Value="EC_Responsiveness.LowCost">
|
||||
<EventProviders>
|
||||
<EventProviderId Value="EP_Microsoft-Windows-XAML-Verbose" />
|
||||
<EventProviderId Value="EP_Microsoft-WindowsMobile-ExecManLogPublisher"/>
|
||||
<EventProviderId Value="EP_Microsoft-WindowsMobile-Compositor" />
|
||||
<EventProviderId Value="EP_Microsoft-WindowsMobile-UIXMobile" />
|
||||
<EventProviderId Value="EP_Microsoft-WindowsMobile-StartMenu" />
|
||||
<EventProviderId Value="EP_Microsoft-WindowsPhone-MobileUI" />
|
||||
</EventProviders>
|
||||
</EventCollectorId>
|
||||
</Collectors>
|
||||
</Profile>
|
||||
<Profile Id="AppLifecycle.Responsiveness.Diagnostic.Verbose.Memory" Base="AppLifecycle.Responsiveness.Light.File" LoggingMode="Memory" Name="AppLifecycle.Responsiveness.Diagnostic" DetailLevel="Verbose" Description="App life cycle responsiveness verbose to memory">
|
||||
<Collectors>
|
||||
<SystemCollectorId Value="SC_Responsiveness.HighCost.Verbose">
|
||||
<SystemProviderId Value="SP_Responsiveness"/>
|
||||
</SystemCollectorId>
|
||||
<EventCollectorId Value="EC_Responsiveness.HighCost.Verbose">
|
||||
<EventProviders>
|
||||
<EventProviderId Value="EP_Microsoft-Windows-ProcessLifetimeManager" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Shell-CortanaSearch"/>
|
||||
<EventProviderId Value="EP_Microsoft-WindowsMobile-ExecManLogPublisher"/>
|
||||
<EventProviderId Value="EP_Microsoft-WindowsMobile-Compositor" />
|
||||
<EventProviderId Value="EP_Microsoft-WindowsMobile-UIXMobile" />
|
||||
<EventProviderId Value="EP_Microsoft-WindowsMobile-StartMenu" />
|
||||
<EventProviderId Value="EP_Microsoft-WindowsPhone-MobileUI" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Kernel-Power" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Kernel-Processor-Power" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Kernel-Pep" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Kernel-Acpi" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-UserModePowerService" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Dwm-Core" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-ImageLoad" />
|
||||
<EventProviderId Value="EP_Microsoft.ClipC" />
|
||||
<EventProviderId Value="EP_Microsoft.ClipSp" />
|
||||
<EventProviderId Value="EP_Microsoft.ClipSvc" />
|
||||
<EventProviderId Value="EP_Microsoft.Windows.LicenseManager.Telemetry" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Win32k" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Kernel-Prefetch" />
|
||||
</EventProviders>
|
||||
</EventCollectorId>
|
||||
</Collectors>
|
||||
</Profile>
|
||||
<Profile Id="AppLifecycle.Memory.Light.File" LoggingMode="File" Name="AppLifecycle.Memory" DetailLevel="Light" Description="App lifecycle memory light to file">
|
||||
<Collectors>
|
||||
<SystemCollectorId Value="SC_Memory.LowCost.Light">
|
||||
<SystemProviderId Value="SP_Memory.Light" />
|
||||
</SystemCollectorId>
|
||||
<EventCollectorId Value="EC_Memory.LowCost.Light">
|
||||
<EventProviders>
|
||||
<EventProviderId Value="EP_Microsoft-Windows-TestExecution" />
|
||||
<EventProviderId Value="EP_Microsoft.Windows.WinPerf" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Immersive-Shell"/>
|
||||
<EventProviderId Value="EP_Microsoft-Windows-AppModel-Exec"/>
|
||||
<EventProviderId Value="EP_Microsoft.Windows.ActivationManager" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-AppLifeCycle" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-AppLifeCycle-UI" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Kernel-EventTracing" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Desktop-ApplicationFrame" />
|
||||
<EventProviderId Value="EP_XNA" />
|
||||
<EventProviderId Value="EP_TaskHost" />
|
||||
<EventProviderId Value="EP_Device-Health-Etw" />
|
||||
<EventProviderId Value="EP_Microsoft-WindowsMobile-ExecManLogPublisher"/>
|
||||
<EventProviderId Value="EP_Microsoft-Microsoft-Phone-AppLifecycle"/>
|
||||
<EventProviderId Value="EP_Microsoft-WindowsPhone-CoreUIComponents"/>
|
||||
<EventProviderId Value="EP_Microsoft-WindowsPhone-AppPlatProvider" />
|
||||
<EventProviderId Value="EP_Microsoft-WindowsPhone-Silverlight" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-XAML-Light" />
|
||||
<EventProviderId Value="EP_Microsoft-WindowsMobile-Splash" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Kernel-Prefetch" />
|
||||
</EventProviders>
|
||||
</EventCollectorId>
|
||||
<EventCollectorId Value="EC_Responsiveness.LowCost.Light.UTC">
|
||||
<EventProviders>
|
||||
<EventProviderId Value="EP_UTC"/>
|
||||
</EventProviders>
|
||||
</EventCollectorId>
|
||||
</Collectors>
|
||||
</Profile>
|
||||
<Profile Id="AppLifecycle.Memory.Diagnostic.Verbose.File" Base="AppLifecycle.Memory.Light.File" LoggingMode="File" Name="AppLifecycle.Memory.Diagnostic" DetailLevel="Verbose" Description="App lifecycle memory verbose to file">
|
||||
<Collectors Operation="Add">
|
||||
<SystemCollectorId Value="SC_Memory.HighCost.Verbose">
|
||||
<SystemProviderId Value="SP_Memory" />
|
||||
</SystemCollectorId>
|
||||
<EventCollectorId Value="EC_Memory.LowCost.Light">
|
||||
<EventProviders>
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Shell-Launcher" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-XAML-Verbose" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Kernel-Power" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Kernel-Processor-Power" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Kernel-Pep" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Dwm-Core" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-ImageLoad" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Kernel-Process" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-Shell-CortanaSearch"/>
|
||||
<EventProviderId Value="EP_Microsoft-WindowsMobile-Compositor" />
|
||||
<EventProviderId Value="EP_Microsoft-WindowsMobile-UIXMobile" />
|
||||
<EventProviderId Value="EP_Microsoft-WindowsMobile-StartMenu" />
|
||||
<EventProviderId Value="EP_Microsoft-WindowsPhone-MobileUI" />
|
||||
<EventProviderId Value="EP_Microsoft-Windows-ProcessLifetimeManager" />
|
||||
</EventProviders>
|
||||
</EventCollectorId>
|
||||
</Collectors>
|
||||
</Profile>
|
||||
</Profiles>
|
||||
<TraceMergeProperties>
|
||||
<TraceMergeProperty Id="TraceMerge_Default" Name="TraceMerge_Default" Base="">
|
||||
<DeletePreMergedTraceFiles Value="true"/>
|
||||
<CustomEvents>
|
||||
<CustomEvent Value="ImageId"/>
|
||||
<CustomEvent Value="BuildInfo"/>
|
||||
<CustomEvent Value="VolumeMapping"/>
|
||||
<CustomEvent Value="EventMetadata"/>
|
||||
<CustomEvent Value="PerfTrackMetadata"/>
|
||||
<CustomEvent Value="WinSAT"/>
|
||||
<CustomEvent Value="NetworkInterface"/>
|
||||
</CustomEvents>
|
||||
</TraceMergeProperty>
|
||||
</TraceMergeProperties>
|
||||
</WindowsPerformanceRecorder>
|
364
internal/Calculator.UITests/Config/AppLifecycle.Regions.tt
Normal file
@@ -0,0 +1,364 @@
|
||||
<# // Copyright (c) Microsoft Corporation. All rights reserved. #>
|
||||
<#@ template language="C#" hostspecific="True" #>
|
||||
<#@ output extension=".xml" #>
|
||||
<# // Set options specific to your app here
|
||||
var options = new {
|
||||
RegionPrefix = "Calculator",
|
||||
ImageFileName = "Calculator.exe",
|
||||
PackageFamilyName = "Microsoft.WindowsCalculator",
|
||||
FirstView = "ms-resource:///Files/Views/MainPage.xbf"
|
||||
};
|
||||
#>
|
||||
<?xml version='1.0' encoding='utf-8' standalone='yes'?>
|
||||
|
||||
<!--
|
||||
Based on:
|
||||
\base\PerfTest\MemRe\AppLifecycle\Common\Regions\Regions_Calculator.xml Regions_Calculator.xml
|
||||
|
||||
This is a regions of interest file that can be used by WPA to get a quick overview of the time
|
||||
spent on a set of operations called "regions".
|
||||
|
||||
A region is defined as the combination of a Start and a Stop event.
|
||||
|
||||
This file contains regions that are of interest for the startup of a UWP app.
|
||||
The first region "<#= options.RegionPrefix #>_AppLifecycle" is defined by the Start and Stop event of the test.
|
||||
Subsequent regions are defined as children of this region to make sure we are only tracking
|
||||
events that occurred during the test.
|
||||
|
||||
The events that are defined as Start and Stop events must come from an event provider that is enabled for the
|
||||
trace that is being analyzed. For WinPerf, that means that the WPR Profile must have these providers enabled.
|
||||
-->
|
||||
|
||||
<?Copyright (c) Microsoft Corporation. All rights reserved.?>
|
||||
<InstrumentationManifest>
|
||||
<Instrumentation>
|
||||
<Regions>
|
||||
<RegionRoot Guid="{7e8672b5-efe5-4862-90f3-944f136d6c75}"
|
||||
Name="<#= options.RegionPrefix #>_AppLifeCycle Region Root"
|
||||
FriendlyName="Root">
|
||||
<Region Guid="{cf6c4996-1dc8-4fc5-b275-7a7051376f77}"
|
||||
Name="<#= options.RegionPrefix #>_AppLifeCycle"
|
||||
FriendlyName="Application Life Cycle Test">
|
||||
<Start>
|
||||
<!-- Microsoft-Windows-TestExecution\RunTest_TestRunScope\win:Start -->
|
||||
<Event Provider="{70d27130-f2f3-4365-b790-d31223254ef4}" Name="RunTest_TestRunScope" Opcode="1"/>
|
||||
<!-- Match the name of the test we are running. -->
|
||||
<PayloadIdentifier FieldName="Name" FieldValue="Calculator.PerfTests.AppLifecycleTests.*" FieldValueRelationship="RegEx"/>
|
||||
</Start>
|
||||
<Stop>
|
||||
<!-- Microsoft-Windows-TestExecution\RunTest_TestRunScope\win:Stop -->
|
||||
<Event Provider="{70d27130-f2f3-4365-b790-d31223254ef4}" Name="RunTest_TestRunScope" Opcode="2"/>
|
||||
<!-- Match the name of the test we are running. -->
|
||||
<PayloadIdentifier FieldName="Name" FieldValue="Calculator.PerfTests.AppLifecycleTests.*" FieldValueRelationship="RegEx"/>
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PayloadBased NameField="Name"/>
|
||||
</Naming>
|
||||
<Region Guid="{b18b32ec-6796-43e1-802f-aec9aea5eb28}"
|
||||
Name="<#= options.RegionPrefix #>_Launch_ProcessStart"
|
||||
FriendlyName="Process Started">
|
||||
<Start>
|
||||
<!-- Use AAMShim_ActivationStart instead of AppLaunch_UserClick as we don't lanch from Start -->
|
||||
<Event Provider="{cf7f94b3-08dc-5257-422f-497d7dc86ab3}" Name="AAMShim_ActivationStart" />
|
||||
<PayloadIdentifier FieldName="AppId" FieldValue="<#= options.PackageFamilyName #>.*" FieldValueRelationship="RegEx" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<Event Provider="{2839ff94-8f12-4e1b-82e3-af7af77a450f}" Name="ProcessStarted" Version="0" />
|
||||
<PayloadIdentifier FieldName="ImageFileName" FieldValue=".*<#= options.ImageFileName #>" FieldValueRelationship="RegEx" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
<Region Guid="{b1e4255d-131c-4ea8-899d-30b7345bf7d3}"
|
||||
Name="<#= options.RegionPrefix #>_Launch_UIThreadStart"
|
||||
FriendlyName="UI Thread Started">
|
||||
<Start>
|
||||
<!-- Use AAMShim_ActivationStart instead of AppLaunch_UserClick as we don't lanch from Start -->
|
||||
<Event Provider="{cf7f94b3-08dc-5257-422f-497d7dc86ab3}" Name="AAMShim_ActivationStart" />
|
||||
<PayloadIdentifier FieldName="AppId" FieldValue="<#= options.PackageFamilyName #>.*" FieldValueRelationship="RegEx" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<!-- Ideally use actual thread start event, for now it's just close, using InitializeCore -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="31" Version="0" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
<Region Guid="{38084b96-d955-4603-a2c7-2720195ce160}"
|
||||
Name="<#= options.RegionPrefix #>_Launch_InitializeCore"
|
||||
FriendlyName="Create XAML Core">
|
||||
<Start>
|
||||
<!-- Initialize Core Start -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="31" Version="0" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<!-- Initialize Core Stop -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="32" Version="0" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
<Region Guid="{cc909ec4-17c0-4cd9-9a83-293e06e0dc72}"
|
||||
Name="<#= options.RegionPrefix #>_Launch_CreateDevice"
|
||||
FriendlyName="Create Graphics Device">
|
||||
<Start>
|
||||
<!-- Create Device Start -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="76" Version="0" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<!-- Create Device Stop -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="77" Version="0" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
<Region Guid="{0ed49a01-2604-499e-8003-0878b3b3c61e}"
|
||||
Name="<#= options.RegionPrefix #>_Launch_CreateResourceManager"
|
||||
FriendlyName="Create Resource Manager">
|
||||
<Start>
|
||||
<!-- Create Resource Manager Start -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="463" Version="0" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<!-- Create Resource Manager Stop -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="464" Version="0" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
<Region Guid="{365920df-10e7-4b6e-8dcb-e769844ac11f}"
|
||||
Name="<#= options.RegionPrefix #>_Launch_CreateWindow"
|
||||
FriendlyName="Create Window">
|
||||
<Start>
|
||||
<!-- Create Window Start -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="29" Version="0" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<!-- Create Window Stop -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="30" Version="0" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
<Region Guid="{09995446-0266-4a34-aa39-d99467dfe85d}"
|
||||
Name="<#= options.RegionPrefix #>_Launch_InitializeTheme"
|
||||
FriendlyName="Initialize Theme Resources">
|
||||
<Start>
|
||||
<!-- Theme Changed Start -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="457" Version="0" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<!-- Theme Changed Stop -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="458" Version="0" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
<Region Guid="{a2fdff0b-75c8-440d-bb55-b87a3c60d55f}"
|
||||
Name="<#= options.RegionPrefix #>_Launch_NavToFirstFrame"
|
||||
FriendlyName="XAML Navigate To First Frame Drawn">
|
||||
<Start>
|
||||
<!-- Parse XAML -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="1" Version="0" />
|
||||
<PayloadIdentifier FieldName="URI" FieldValue="<#= options.FirstView #>" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<!-- Frame Drawn -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="65" Version="0" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
<Match>
|
||||
<Event PID="true"/>
|
||||
</Match>
|
||||
</Region>
|
||||
<Region Guid="{ffc47f79-2d90-470a-bfde-0d075972f23b}"
|
||||
Name="<#= options.RegionPrefix #>_ApplicationActivate"
|
||||
FriendlyName="Application Activate">
|
||||
<Start>
|
||||
<Event Provider="{315a8872-923e-4ea2-9889-33cd4754bf64}" Id="5901" Version="1" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<Event Provider="{315a8872-923e-4ea2-9889-33cd4754bf64}" Id="5902" Version="1" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
<Region Guid="{b0c74cf1-16fc-4a33-ba7e-2169727a08d7}"
|
||||
Name="<#= options.RegionPrefix #>_Launch_SplashScreen"
|
||||
FriendlyName="Splash Screen Dismissed">
|
||||
<Start>
|
||||
<!-- Use AAMShim_ActivationStart instead of AppLaunch_UserClick as we don't lanch from Start -->
|
||||
<Event Provider="{cf7f94b3-08dc-5257-422f-497d7dc86ab3}" Name="AAMShim_ActivationStart" />
|
||||
<PayloadIdentifier FieldName="AppId" FieldValue="<#= options.PackageFamilyName #>.*" FieldValueRelationship="RegEx" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<!-- NavigationServerTask_SplashScreenDismissed -->
|
||||
<Event Provider="{a0b7550f-4e9a-4f03-ad41-b8042d06a2f7}" Id="1572" Version="0" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
<Region Guid="{a1648637-d5ec-46d2-9655-a26d00a35764}"
|
||||
Name="<#= options.RegionPrefix #>_Launch_UIResponsive"
|
||||
FriendlyName="UI Responsive">
|
||||
<Start>
|
||||
<!-- Use AAMShim_ActivationStart instead of AppLaunch_UserClick as we don't lanch from Start -->
|
||||
<Event Provider="{cf7f94b3-08dc-5257-422f-497d7dc86ab3}" Name="AAMShim_ActivationStart" />
|
||||
<PayloadIdentifier FieldName="AppId" FieldValue="<#= options.PackageFamilyName #>.*" FieldValueRelationship="RegEx" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<Event Provider="{EF00584A-2655-462C-BC24-E7DE630E7FBF}" Name="ModernAppLaunch_UIResponsive" Version="0" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
<Region Guid="{74d63c4e-7dd7-4ff6-9ee8-adb462c1c101}"
|
||||
Name="<#= options.RegionPrefix #>_Launch_VisibleComplete"
|
||||
FriendlyName="Visible Complete">
|
||||
<Start>
|
||||
<!-- Use AAMShim_ActivationStart instead of AppLaunch_UserClick as we don't lanch from Start -->
|
||||
<Event Provider="{cf7f94b3-08dc-5257-422f-497d7dc86ab3}" Name="AAMShim_ActivationStart" />
|
||||
<PayloadIdentifier FieldName="AppId" FieldValue="<#= options.PackageFamilyName #>.*" FieldValueRelationship="RegEx" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<Event Provider="{EF00584A-2655-462C-BC24-E7DE630E7FBF}" Name="ModernAppLaunch_VisibleComplete" Version="0" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
<Region Guid="{ec31fb10-992b-438b-8c9e-42454f4b2e5a}"
|
||||
Name="<#= options.RegionPrefix #>_Suspend"
|
||||
FriendlyName="Suspended">
|
||||
<Start>
|
||||
<!-- Microsoft-Windows-Immersive-Shell\PerfTrack_PLM_SuspendApplication\win:Start -->
|
||||
<Event Provider="{315a8872-923e-4ea2-9889-33cd4754bf64}" Id="2450" Version="1" />
|
||||
<PayloadIdentifier FieldName="PsmKey" FieldValueRelationship="RegEx" FieldValue="<#= options.PackageFamilyName #>.*" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<!-- Microsoft-Windows-Immersive-Shell\PerfTrack_PLM_SuspendApplication\win:Stop -->
|
||||
<Event Provider="{315a8872-923e-4ea2-9889-33cd4754bf64}" Id="2451" Version="1" />
|
||||
<PayloadIdentifier FieldName="AppUserModelId" FieldValue="<#= options.PackageFamilyName #>.*" FieldValueRelationship="RegEx" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
<Region Guid="{83735b08-b17e-48cf-82f1-02cb08e45597}"
|
||||
Name="<#= options.RegionPrefix #>_Resume"
|
||||
FriendlyName="Resumed">
|
||||
<Start>
|
||||
<!-- Microsoft-Windows-Immersive-Shell\PerfTrack_PLM_ResumeApplication_EndToEnd\win:Start -->
|
||||
<Event Provider="{315a8872-923e-4ea2-9889-33cd4754bf64}" Id="11118" Version="0" />
|
||||
<PayloadIdentifier FieldName="PsmKey" FieldValueRelationship="RegEx" FieldValue="<#= options.PackageFamilyName #>.*" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<!-- Microsoft-Windows-Immersive-Shell\PerfTrack_PLM_ResumeApplication_EndToEnd\win:Stop -->
|
||||
<Event Provider="{315a8872-923e-4ea2-9889-33cd4754bf64}" Id="11119" Version="0" />
|
||||
<PayloadIdentifier FieldName="AppUserModelId" FieldValue="<#= options.PackageFamilyName #>.*" FieldValueRelationship="RegEx" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName><#= options.ImageFileName #></WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
</Region>
|
||||
</RegionRoot>
|
||||
</Regions>
|
||||
</Instrumentation>
|
||||
</InstrumentationManifest>
|
353
internal/Calculator.UITests/Config/AppLifecycle.Regions.xml
Normal file
@@ -0,0 +1,353 @@
|
||||
<?xml version='1.0' encoding='utf-8' standalone='yes'?>
|
||||
|
||||
<!--
|
||||
Based on:
|
||||
\base\PerfTest\MemRe\AppLifecycle\Common\Regions\Regions_Calculator.xml Regions_Calculator.xml
|
||||
|
||||
This is a regions of interest file that can be used by WPA to get a quick overview of the time
|
||||
spent on a set of operations called "regions".
|
||||
|
||||
A region is defined as the combination of a Start and a Stop event.
|
||||
|
||||
This file contains regions that are of interest for the startup of a UWP app.
|
||||
The first region "Calculator_AppLifecycle" is defined by the Start and Stop event of the test.
|
||||
Subsequent regions are defined as children of this region to make sure we are only tracking
|
||||
events that occurred during the test.
|
||||
|
||||
The events that are defined as Start and Stop events must come from an event provider that is enabled for the
|
||||
trace that is being analyzed. For WinPerf, that means that the WPR Profile must have these providers enabled.
|
||||
-->
|
||||
|
||||
<?Copyright (c) Microsoft Corporation. All rights reserved.?>
|
||||
<InstrumentationManifest>
|
||||
<Instrumentation>
|
||||
<Regions>
|
||||
<RegionRoot Guid="{7e8672b5-efe5-4862-90f3-944f136d6c75}"
|
||||
Name="Calculator_AppLifeCycle Region Root"
|
||||
FriendlyName="Root">
|
||||
<Region Guid="{cf6c4996-1dc8-4fc5-b275-7a7051376f77}"
|
||||
Name="Calculator_AppLifeCycle"
|
||||
FriendlyName="Application Life Cycle Test">
|
||||
<Start>
|
||||
<!-- Microsoft-Windows-TestExecution\TE_TestRun\win:Start -->
|
||||
<Event Provider="{065903c1-4883-4fb8-b163-d02bd5efc74c}" Id="7" Version="0" />
|
||||
<!-- Match the name of the test we are running. -->
|
||||
<PayloadIdentifier FieldName="Name" FieldValue="Calculator.PerfTests.AppLifecycleTests.*" FieldValueRelationship="RegEx"/>
|
||||
</Start>
|
||||
<Stop>
|
||||
<!-- Microsoft-Windows-TestExecution\TE_TestRun\win:Stop -->
|
||||
<Event Provider="{065903c1-4883-4fb8-b163-d02bd5efc74c}" Id="8" Version="0" />
|
||||
<!-- Match the name of the test we are running. -->
|
||||
<PayloadIdentifier FieldName="Name" FieldValue="Calculator.PerfTests.AppLifecycleTests.*" FieldValueRelationship="RegEx"/>
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PayloadBased NameField="Name"/>
|
||||
</Naming>
|
||||
<Region Guid="{b18b32ec-6796-43e1-802f-aec9aea5eb28}"
|
||||
Name="Calculator_Launch_ProcessStart"
|
||||
FriendlyName="Process Started">
|
||||
<Start>
|
||||
<!-- Use AAMShim_ActivationStart instead of AppLaunch_UserClick as we don't lanch from Start -->
|
||||
<Event Provider="{cf7f94b3-08dc-5257-422f-497d7dc86ab3}" Name="AAMShim_ActivationStart" />
|
||||
<PayloadIdentifier FieldName="AppId" FieldValue="Microsoft.WindowsCalculator.*" FieldValueRelationship="RegEx" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<Event Provider="{2839ff94-8f12-4e1b-82e3-af7af77a450f}" Name="ProcessStarted" Version="0" />
|
||||
<PayloadIdentifier FieldName="ImageFileName" FieldValue=".*Calculator.exe" FieldValueRelationship="RegEx" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName>Calculator.exe</WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName>Calculator.exe</WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
<Region Guid="{b1e4255d-131c-4ea8-899d-30b7345bf7d3}"
|
||||
Name="Calculator_Launch_UIThreadStart"
|
||||
FriendlyName="UI Thread Started">
|
||||
<Start>
|
||||
<!-- Use AAMShim_ActivationStart instead of AppLaunch_UserClick as we don't lanch from Start -->
|
||||
<Event Provider="{cf7f94b3-08dc-5257-422f-497d7dc86ab3}" Name="AAMShim_ActivationStart" />
|
||||
<PayloadIdentifier FieldName="AppId" FieldValue="Microsoft.WindowsCalculator.*" FieldValueRelationship="RegEx" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<!-- Ideally use actual thread start event, for now it's just close, using InitializeCore -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="31" Version="0" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName>Calculator.exe</WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName>Calculator.exe</WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
<Region Guid="{38084b96-d955-4603-a2c7-2720195ce160}"
|
||||
Name="Calculator_Launch_InitializeCore"
|
||||
FriendlyName="Create XAML Core">
|
||||
<Start>
|
||||
<!-- Initialize Core Start -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="31" Version="0" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<!-- Initialize Core Stop -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="32" Version="0" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName>Calculator.exe</WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName>Calculator.exe</WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
<Region Guid="{cc909ec4-17c0-4cd9-9a83-293e06e0dc72}"
|
||||
Name="Calculator_Launch_CreateDevice"
|
||||
FriendlyName="Create Graphics Device">
|
||||
<Start>
|
||||
<!-- Create Device Start -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="76" Version="0" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<!-- Create Device Stop -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="77" Version="0" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName>Calculator.exe</WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName>Calculator.exe</WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
<Region Guid="{0ed49a01-2604-499e-8003-0878b3b3c61e}"
|
||||
Name="Calculator_Launch_CreateResourceManager"
|
||||
FriendlyName="Create Resource Manager">
|
||||
<Start>
|
||||
<!-- Create Resource Manager Start -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="463" Version="0" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<!-- Create Resource Manager Stop -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="464" Version="0" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName>Calculator.exe</WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName>Calculator.exe</WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
<Region Guid="{365920df-10e7-4b6e-8dcb-e769844ac11f}"
|
||||
Name="Calculator_Launch_CreateWindow"
|
||||
FriendlyName="Create Window">
|
||||
<Start>
|
||||
<!-- Create Window Start -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="29" Version="0" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<!-- Create Window Stop -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="30" Version="0" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName>Calculator.exe</WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName>Calculator.exe</WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
<Region Guid="{09995446-0266-4a34-aa39-d99467dfe85d}"
|
||||
Name="Calculator_Launch_InitializeTheme"
|
||||
FriendlyName="Initialize Theme Resources">
|
||||
<Start>
|
||||
<!-- Theme Changed Start -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="457" Version="0" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<!-- Theme Changed Stop -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="458" Version="0" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName>Calculator.exe</WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName>Calculator.exe</WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
<Region Guid="{a2fdff0b-75c8-440d-bb55-b87a3c60d55f}"
|
||||
Name="Calculator_Launch_NavToFirstFrame"
|
||||
FriendlyName="XAML Navigate To First Frame Drawn">
|
||||
<Start>
|
||||
<!-- Parse XAML -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="1" Version="0" />
|
||||
<PayloadIdentifier FieldName="URI" FieldValue="ms-resource:///Files/Views/MainPage.xbf" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<!-- Frame Drawn -->
|
||||
<Event Provider="{531A35AB-63CE-4BCF-AA98-F88C7A89E455}" Id="65" Version="0" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName>Calculator.exe</WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName>Calculator.exe</WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
<Match>
|
||||
<Event PID="true"/>
|
||||
</Match>
|
||||
</Region>
|
||||
<Region Guid="{ffc47f79-2d90-470a-bfde-0d075972f23b}"
|
||||
Name="Calculator_ApplicationActivate"
|
||||
FriendlyName="Application Activate">
|
||||
<Start>
|
||||
<Event Provider="{315a8872-923e-4ea2-9889-33cd4754bf64}" Id="5901" Version="1" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<Event Provider="{315a8872-923e-4ea2-9889-33cd4754bf64}" Id="5902" Version="1" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName>Calculator.exe</WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName>Calculator.exe</WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
<Region Guid="{b0c74cf1-16fc-4a33-ba7e-2169727a08d7}"
|
||||
Name="Calculator_Launch_SplashScreen"
|
||||
FriendlyName="Splash Screen Dismissed">
|
||||
<Start>
|
||||
<!-- Use AAMShim_ActivationStart instead of AppLaunch_UserClick as we don't lanch from Start -->
|
||||
<Event Provider="{cf7f94b3-08dc-5257-422f-497d7dc86ab3}" Name="AAMShim_ActivationStart" />
|
||||
<PayloadIdentifier FieldName="AppId" FieldValue="Microsoft.WindowsCalculator.*" FieldValueRelationship="RegEx" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<!-- NavigationServerTask_SplashScreenDismissed -->
|
||||
<Event Provider="{a0b7550f-4e9a-4f03-ad41-b8042d06a2f7}" Id="1572" Version="0" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName>Calculator.exe</WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName>Calculator.exe</WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
<Region Guid="{a1648637-d5ec-46d2-9655-a26d00a35764}"
|
||||
Name="Calculator_Launch_UIResponsive"
|
||||
FriendlyName="UI Responsive">
|
||||
<Start>
|
||||
<!-- Use AAMShim_ActivationStart instead of AppLaunch_UserClick as we don't lanch from Start -->
|
||||
<Event Provider="{cf7f94b3-08dc-5257-422f-497d7dc86ab3}" Name="AAMShim_ActivationStart" />
|
||||
<PayloadIdentifier FieldName="AppId" FieldValue="Microsoft.WindowsCalculator.*" FieldValueRelationship="RegEx" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<Event Provider="{EF00584A-2655-462C-BC24-E7DE630E7FBF}" Name="ModernAppLaunch_UIResponsive" Version="0" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName>Calculator.exe</WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName>Calculator.exe</WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
<Region Guid="{74d63c4e-7dd7-4ff6-9ee8-adb462c1c101}"
|
||||
Name="Calculator_Launch_VisibleComplete"
|
||||
FriendlyName="Visible Complete">
|
||||
<Start>
|
||||
<!-- Use AAMShim_ActivationStart instead of AppLaunch_UserClick as we don't lanch from Start -->
|
||||
<Event Provider="{cf7f94b3-08dc-5257-422f-497d7dc86ab3}" Name="AAMShim_ActivationStart" />
|
||||
<PayloadIdentifier FieldName="AppId" FieldValue="Microsoft.WindowsCalculator.*" FieldValueRelationship="RegEx" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<Event Provider="{EF00584A-2655-462C-BC24-E7DE630E7FBF}" Name="ModernAppLaunch_VisibleComplete" Version="0" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName>Calculator.exe</WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName>Calculator.exe</WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
<Region Guid="{ec31fb10-992b-438b-8c9e-42454f4b2e5a}"
|
||||
Name="Calculator_Suspend"
|
||||
FriendlyName="Suspended">
|
||||
<Start>
|
||||
<!-- Microsoft-Windows-Immersive-Shell\PerfTrack_PLM_SuspendApplication\win:Start -->
|
||||
<Event Provider="{315a8872-923e-4ea2-9889-33cd4754bf64}" Id="2450" Version="1" />
|
||||
<PayloadIdentifier FieldName="PsmKey" FieldValueRelationship="RegEx" FieldValue="Microsoft.WindowsCalculator.*" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<!-- Microsoft-Windows-Immersive-Shell\PerfTrack_PLM_SuspendApplication\win:Stop -->
|
||||
<Event Provider="{315a8872-923e-4ea2-9889-33cd4754bf64}" Id="2451" Version="1" />
|
||||
<PayloadIdentifier FieldName="AppUserModelId" FieldValue="Microsoft.WindowsCalculator.*" FieldValueRelationship="RegEx" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName>Calculator.exe</WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName>Calculator.exe</WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
<Region Guid="{83735b08-b17e-48cf-82f1-02cb08e45597}"
|
||||
Name="Calculator_Resume"
|
||||
FriendlyName="Resumed">
|
||||
<Start>
|
||||
<!-- Microsoft-Windows-Immersive-Shell\PerfTrack_PLM_ResumeApplication_EndToEnd\win:Start -->
|
||||
<Event Provider="{315a8872-923e-4ea2-9889-33cd4754bf64}" Id="11118" Version="0" />
|
||||
<PayloadIdentifier FieldName="PsmKey" FieldValueRelationship="RegEx" FieldValue="Microsoft.WindowsCalculator.*" />
|
||||
</Start>
|
||||
<Stop>
|
||||
<!-- Microsoft-Windows-Immersive-Shell\PerfTrack_PLM_ResumeApplication_EndToEnd\win:Stop -->
|
||||
<Event Provider="{315a8872-923e-4ea2-9889-33cd4754bf64}" Id="11119" Version="0" />
|
||||
<PayloadIdentifier FieldName="AppUserModelId" FieldValue="Microsoft.WindowsCalculator.*" FieldValueRelationship="RegEx" />
|
||||
</Stop>
|
||||
<Naming>
|
||||
<PrependParentName />
|
||||
</Naming>
|
||||
<Metadata>
|
||||
<WinperfWPAPreset.1>CPU</WinperfWPAPreset.1>
|
||||
<WinperfWPAPreset.1.ProcessName>Calculator.exe</WinperfWPAPreset.1.ProcessName>
|
||||
<WinperfWPAPreset.2>Commit</WinperfWPAPreset.2>
|
||||
<WinperfWPAPreset.2.ProcessName>Calculator.exe</WinperfWPAPreset.2.ProcessName>
|
||||
</Metadata>
|
||||
</Region>
|
||||
</Region>
|
||||
</RegionRoot>
|
||||
</Regions>
|
||||
</Instrumentation>
|
||||
</InstrumentationManifest>
|
54
internal/Calculator.UITests/Initialization.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using Calculator.UIAutomationLibrary;
|
||||
using Microsoft.OneCoreUap.Test.AppModel;
|
||||
using WEX.TestExecution;
|
||||
using WEX.TestExecution.Markup;
|
||||
|
||||
namespace Calculator.UITests
|
||||
{
|
||||
[TestClass]
|
||||
public class Initialization
|
||||
{
|
||||
[DllImport("AppModel.TestHelper.dll")]
|
||||
private static extern Int32 WinRTHelper_Register();
|
||||
|
||||
[AssemblyInitialize]
|
||||
[TestProperty("CoreClrProfile", "TestNetv2.0")]
|
||||
[TestProperty("RunFixtureAs:Assembly", "System")]
|
||||
public static void AssemblySetup(TestContext context)
|
||||
{
|
||||
Verify.AreEqual(0, WinRTHelper_Register());
|
||||
TestHelper.Initialize();
|
||||
|
||||
// Install and Start the Etw.Service service to enable the use of EtwWaiter.
|
||||
EtwHelper.InstallAndStartETWService();
|
||||
|
||||
bool installApp = false;
|
||||
if (context.Properties.Contains("InstallApp") && (bool.TryParse(context.Properties["InstallApp"].ToString(), out installApp)) && installApp)
|
||||
{
|
||||
string certToDeploy = Path.Combine(TAEFHelper.GetTestDeploymentDirectory(), Constants.CertificateFileName);
|
||||
InstallHelper.InstallCertFile(certToDeploy);
|
||||
|
||||
string vcLibsToDeploy = Path.Combine(TAEFHelper.GetTestDeploymentDirectory(), Constants.VCLibsPackageFileName);
|
||||
string winUIToDeploy = Path.Combine(TAEFHelper.GetTestDeploymentDirectory(), Constants.WinUIPackageFileName);
|
||||
string appxToDeploy = Path.Combine(TAEFHelper.GetTestDeploymentDirectory(), Constants.PackageFileName);
|
||||
Impersonater.RunAs(Impersonater.RunAsUser.RestrictedUser, () => InstallHelper.InstallPackage(appxToDeploy, vcLibsToDeploy, winUIToDeploy));
|
||||
}
|
||||
}
|
||||
|
||||
[AssemblyCleanup]
|
||||
[TestProperty("RunFixtureAs:Assembly", "System")]
|
||||
public static void AssemblyCleanup()
|
||||
{
|
||||
// Stop and remove the Etw.Service service.
|
||||
EtwHelper.StopAndRemoveETWService();
|
||||
|
||||
TestHelper.Uninitialize();
|
||||
}
|
||||
}
|
||||
}
|
21
internal/Calculator.UITests/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("UIAutomationTests")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("f5e8f9b8-f7f1-4300-a5cb-35bfab83f51e")]
|
||||
// The following was autogenerated by UpdateVersion.ps1
|
||||
[assembly: AssemblyProduct(@"10.16.1128.1252")]
|
51
internal/Calculator.UITests/Tests/AppLifecycleTests.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Etw.Managed;
|
||||
using Microsoft.Windows.Apps.Performance;
|
||||
using WEX.Logging.Interop;
|
||||
using WEX.TestExecution;
|
||||
using WEX.TestExecution.Markup;
|
||||
using Calculator.UIAutomationLibrary;
|
||||
|
||||
namespace Calculator.PerfTests
|
||||
{
|
||||
[TestClass]
|
||||
public class AppLifecycleTests
|
||||
{
|
||||
[TestInitialize]
|
||||
[TestProperty("RunAs", "ElevatedUserOrSystem")]
|
||||
public void MethodSetup()
|
||||
{
|
||||
Utilities.KillExistingCalculatorProcesses();
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
[TestProperty("RunAs", "ElevatedUserOrSystem")]
|
||||
public void MethodCleanup()
|
||||
{
|
||||
Utilities.KillExistingCalculatorProcesses();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method executes the AppLifecycle performance test.
|
||||
/// The test launches the application, suspend and resumes it and then terminates the app.
|
||||
///
|
||||
/// A TAEF data source is used to specify the Windows Performance Recorder profile and
|
||||
/// regions of interest file to use and defines threee different configurations to execute this test with.
|
||||
/// Cold: The initial run to get dlls loaded into memory and to execute any first-run app logic.
|
||||
/// Warm: The run that will produce consistent results and that would be used for measures.
|
||||
/// Memory: A run that is focused on collecting more info on allocations.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
[TestProperty("RunAs", "User")]
|
||||
[TestProperty("Category", "Performance")]
|
||||
[TestProperty(WinperfConstants.DataSource, PerfConstants.AppLifecycleInterationsSource)]
|
||||
public void AppLifecycleTest()
|
||||
{
|
||||
AppLifecycle.Run(Constants.PackageAppUserModelId);
|
||||
}
|
||||
}
|
||||
}
|
49
internal/Calculator.UITests/Tests/CalculatorTests.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Calculator.UIAutomationLibrary;
|
||||
using Calculator.UIAutomationLibrary.Tests;
|
||||
using WEX.TestExecution.Markup;
|
||||
|
||||
namespace Calculator.UITests
|
||||
{
|
||||
[TestClass]
|
||||
public class CalculatorTests
|
||||
{
|
||||
[TestInitialize]
|
||||
[TestProperty("RunAs", "ElevatedUserOrSystem")]
|
||||
public void MethodSetup()
|
||||
{
|
||||
Utilities.KillExistingCalculatorProcesses();
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
[TestProperty("RunAs", "ElevatedUserOrSystem")]
|
||||
public void MethodCleanup()
|
||||
{
|
||||
Utilities.KillExistingCalculatorProcesses();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestProperty("RunAs", "User")]
|
||||
public void OnePlusTwoTest()
|
||||
{
|
||||
var calculatorLfm = CalculatorAppLauncher.Launch();
|
||||
|
||||
calculatorLfm.CalculateOnePlusTwo();
|
||||
|
||||
calculatorLfm.Close();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestProperty("RunAs", "User")]
|
||||
public void Sqrt4Minus2Test()
|
||||
{
|
||||
var calculatorLfm = CalculatorAppLauncher.Launch();
|
||||
|
||||
calculatorLfm.CalculateSqrt4Minus2();
|
||||
|
||||
calculatorLfm.Close();
|
||||
}
|
||||
}
|
||||
}
|
43
internal/Calculator.UITests/Tests/LaunchTests.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using MS.Internal.Mita.Foundation;
|
||||
using MS.Internal.Mita.Foundation.Controls;
|
||||
using MS.Internal.Mita.Foundation.Waiters;
|
||||
using System;
|
||||
using WEX.TestExecution;
|
||||
using WEX.TestExecution.Markup;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.OneCoreUap.Test.AppModel;
|
||||
using System.IO;
|
||||
using Calculator.UITests;
|
||||
using Calculator.UIAutomationLibrary;
|
||||
|
||||
namespace Calculator.UITests
|
||||
{
|
||||
[TestClass]
|
||||
public class LaunchTests
|
||||
{
|
||||
[TestInitialize]
|
||||
[TestProperty("RunAs", "ElevatedUserOrSystem")]
|
||||
public void MethodSetup()
|
||||
{
|
||||
Utilities.KillExistingCalculatorProcesses();
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
[TestProperty("RunAs", "ElevatedUserOrSystem")]
|
||||
public void MethodCleanup()
|
||||
{
|
||||
Utilities.KillExistingCalculatorProcesses();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestProperty("RunAs", "User")]
|
||||
public void NormalLaunchTest()
|
||||
{
|
||||
var calculatorLfm = CalculatorAppLauncher.Launch();
|
||||
calculatorLfm.Close();
|
||||
}
|
||||
}
|
||||
}
|
19
internal/Calculator.UITests/project.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"AppModel.TestHelper": "2018.3.22",
|
||||
"EtwProcessor.Managed": "10.34.181220007",
|
||||
"Microsoft.TestInfrastructure.UniversalTest": "1.0.20181107.1",
|
||||
"Microsoft.Windows.Apps.Performance": "1.0.7",
|
||||
"MITALite": "1.0.180128001",
|
||||
"Taef.Managed": "10.34.181220007",
|
||||
"Test.Net.Redist": "2.0.1"
|
||||
},
|
||||
"frameworks": {
|
||||
"netcore50": {}
|
||||
},
|
||||
"runtimes": {
|
||||
"win10-arm": {},
|
||||
"win10-x64": {},
|
||||
"win10-x86": {}
|
||||
}
|
||||
}
|
73
internal/Calculator.UITests/testmd.definition
Normal file
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"$schema": "http://universaltest/schema/testmddefinition-4.json",
|
||||
"Package": {
|
||||
"ComponentName": "Calculator",
|
||||
"SubComponentName": "UITests"
|
||||
},
|
||||
"SupportedArchitectures": [ "All" ],
|
||||
"Execution": {
|
||||
"Type": "TAEF",
|
||||
"Parameter": "/ScreenCaptureOnError /TestMode:EnsureLoggedOnUser",
|
||||
"ExecutionTimeoutInMinutes": "30"
|
||||
},
|
||||
"Dependencies": {
|
||||
"Files": [
|
||||
{
|
||||
"SourcePath": "$(OUT_DIR)Calculator.UIAutomationLibrary.dll",
|
||||
"DestinationFolderPath": "$$(TEST_DEPLOY_BIN)"
|
||||
},
|
||||
{
|
||||
"SourcePath": "$(OUT_DIR)Microsoft.Windows.Apps.Performance.dll",
|
||||
"DestinationFolderPath": "$$(TEST_DEPLOY_BIN)"
|
||||
},
|
||||
{
|
||||
"SourcePath": "$(OUT_DIR)Config\\AppLifecycle.Profile.wprp",
|
||||
"DestinationFolderPath": "$$(TEST_DEPLOY_BIN)\\Config\\"
|
||||
},
|
||||
{
|
||||
"SourcePath": "$(OUT_DIR)Config\\AppLifecycle.Regions.xml",
|
||||
"DestinationFolderPath": "$$(TEST_DEPLOY_BIN)\\Config\\"
|
||||
},
|
||||
{
|
||||
"SourcePath": "$(OUT_DIR)Config\\AppLifecycle.Iterations.xml",
|
||||
"DestinationFolderPath": "$$(TEST_DEPLOY_BIN)\\Config\\"
|
||||
}
|
||||
],
|
||||
"Packages": [
|
||||
"Microsoft-Windows-Test-Taef",
|
||||
"Microsoft-Windows-Test-EtwProcessor",
|
||||
"Microsoft-Test-Taef-EnsureLoggedOnUserTestMode",
|
||||
"Microsoft-Test-Taef-EtwLoggerTestMode",
|
||||
"Microsoft-Windows-Test-MitaLite",
|
||||
"Microsoft-Windows-Test-TestNetV2.0",
|
||||
"Microsoft-OneCoreUap-Test-AppModel-AreaLibrary"
|
||||
]
|
||||
},
|
||||
"Logs": [],
|
||||
"Plugins": [],
|
||||
"Profiles": [
|
||||
{
|
||||
"Name": "All",
|
||||
"Execution": {
|
||||
"AdditionalParameter": "/TestMode:EtwLogger /p:InstallApp=true /select:not(@Category='Performance')"
|
||||
},
|
||||
"Dependencies": {
|
||||
"AdditionalPackages": [
|
||||
"Microsoft-Calculator-App"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Performance",
|
||||
"Execution": {
|
||||
"AdditionalParameter": "/TestMode:WinPerf /WinPerf:Upload=Full /winperf:WinPerfSource=\"Utility Apps Performance Tests\" /winperf:VersionProcess=Calculator.exe /winperf:VersionImage=Calculator.exe /p:InstallApp=true /select:@Category='Performance'"
|
||||
},
|
||||
"Dependencies": {
|
||||
"AdditionalPackages": [
|
||||
"Microsoft-Windows-Performance-Winperf-Winperf",
|
||||
"Microsoft-Calculator-App"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
165
internal/CalculatorInternal.sln
Normal file
@@ -0,0 +1,165 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27130.2036
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Calculator.UIAutomationLibrary", "Calculator.UIAutomationLibrary\Calculator.UIAutomationLibrary.csproj", "{A43517B5-8BE3-4312-913F-004978C34444}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Calculator.UITests", "Calculator.UITests\Calculator.UITests.csproj", "{0224A709-0C48-4C4F-BA17-843A49842C15}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E73C8A6E-BB94-4258-ACED-7C837A6A587B}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
nuget.config = nuget.config
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Calculator", "..\src\Calculator\Calculator.vcxproj", "{9447424A-0E05-4911-BEB8-E0354405F39A}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalcViewModel", "..\src\CalcViewModel\CalcViewModel.vcxproj", "{90E9761D-9262-4773-942D-CAEAE75D7140}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalcManager", "..\src\CalcManager\CalcManager.vcxproj", "{311E866D-8B93-4609-A691-265941FEE101}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Calculator.TestPackage", "Calculator.TestPackage\Calculator.TestPackage.csproj", "{24767C43-CD5A-4DC9-8D6B-429F255524E5}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalculatorUnitTests", "CalculatorUnitTests\CalculatorUnitTests.vcxproj", "{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM = Debug|ARM
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|ARM = Release|ARM
|
||||
Release|ARM64 = Release|ARM64
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{A43517B5-8BE3-4312-913F-004978C34444}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{A43517B5-8BE3-4312-913F-004978C34444}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{A43517B5-8BE3-4312-913F-004978C34444}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{A43517B5-8BE3-4312-913F-004978C34444}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A43517B5-8BE3-4312-913F-004978C34444}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A43517B5-8BE3-4312-913F-004978C34444}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{A43517B5-8BE3-4312-913F-004978C34444}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{A43517B5-8BE3-4312-913F-004978C34444}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{A43517B5-8BE3-4312-913F-004978C34444}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{A43517B5-8BE3-4312-913F-004978C34444}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{A43517B5-8BE3-4312-913F-004978C34444}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{A43517B5-8BE3-4312-913F-004978C34444}.Release|x64.Build.0 = Release|Any CPU
|
||||
{A43517B5-8BE3-4312-913F-004978C34444}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{A43517B5-8BE3-4312-913F-004978C34444}.Release|x86.Build.0 = Release|Any CPU
|
||||
{0224A709-0C48-4C4F-BA17-843A49842C15}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{0224A709-0C48-4C4F-BA17-843A49842C15}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{0224A709-0C48-4C4F-BA17-843A49842C15}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{0224A709-0C48-4C4F-BA17-843A49842C15}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{0224A709-0C48-4C4F-BA17-843A49842C15}.Debug|x64.Build.0 = Debug|x64
|
||||
{0224A709-0C48-4C4F-BA17-843A49842C15}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{0224A709-0C48-4C4F-BA17-843A49842C15}.Debug|x86.Build.0 = Debug|x86
|
||||
{0224A709-0C48-4C4F-BA17-843A49842C15}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{0224A709-0C48-4C4F-BA17-843A49842C15}.Release|ARM.Build.0 = Release|ARM
|
||||
{0224A709-0C48-4C4F-BA17-843A49842C15}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{0224A709-0C48-4C4F-BA17-843A49842C15}.Release|x64.ActiveCfg = Release|x64
|
||||
{0224A709-0C48-4C4F-BA17-843A49842C15}.Release|x64.Build.0 = Release|x64
|
||||
{0224A709-0C48-4C4F-BA17-843A49842C15}.Release|x86.ActiveCfg = Release|x86
|
||||
{0224A709-0C48-4C4F-BA17-843A49842C15}.Release|x86.Build.0 = Release|x86
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|ARM64.Deploy.0 = Debug|ARM64
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|x64.Build.0 = Debug|x64
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|x86.Build.0 = Debug|Win32
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|x86.Deploy.0 = Debug|Win32
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Release|ARM.Build.0 = Release|ARM
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Release|ARM64.Deploy.0 = Release|ARM64
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Release|x64.ActiveCfg = Release|x64
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Release|x64.Build.0 = Release|x64
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Release|x64.Deploy.0 = Release|x64
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Release|x86.ActiveCfg = Release|Win32
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Release|x86.Build.0 = Release|Win32
|
||||
{9447424A-0E05-4911-BEB8-E0354405F39A}.Release|x86.Deploy.0 = Release|Win32
|
||||
{90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|x64.Build.0 = Debug|x64
|
||||
{90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|x86.Build.0 = Debug|Win32
|
||||
{90E9761D-9262-4773-942D-CAEAE75D7140}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{90E9761D-9262-4773-942D-CAEAE75D7140}.Release|ARM.Build.0 = Release|ARM
|
||||
{90E9761D-9262-4773-942D-CAEAE75D7140}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{90E9761D-9262-4773-942D-CAEAE75D7140}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{90E9761D-9262-4773-942D-CAEAE75D7140}.Release|x64.ActiveCfg = Release|x64
|
||||
{90E9761D-9262-4773-942D-CAEAE75D7140}.Release|x64.Build.0 = Release|x64
|
||||
{90E9761D-9262-4773-942D-CAEAE75D7140}.Release|x86.ActiveCfg = Release|Win32
|
||||
{90E9761D-9262-4773-942D-CAEAE75D7140}.Release|x86.Build.0 = Release|Win32
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Debug|x64.Build.0 = Debug|x64
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Debug|x86.Build.0 = Debug|Win32
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Release|ARM.Build.0 = Release|ARM
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Release|x64.ActiveCfg = Release|x64
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Release|x64.Build.0 = Release|x64
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Release|x86.ActiveCfg = Release|Win32
|
||||
{311E866D-8B93-4609-A691-265941FEE101}.Release|x86.Build.0 = Release|Win32
|
||||
{24767C43-CD5A-4DC9-8D6B-429F255524E5}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{24767C43-CD5A-4DC9-8D6B-429F255524E5}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{24767C43-CD5A-4DC9-8D6B-429F255524E5}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{24767C43-CD5A-4DC9-8D6B-429F255524E5}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{24767C43-CD5A-4DC9-8D6B-429F255524E5}.Debug|x64.Build.0 = Debug|x64
|
||||
{24767C43-CD5A-4DC9-8D6B-429F255524E5}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{24767C43-CD5A-4DC9-8D6B-429F255524E5}.Debug|x86.Build.0 = Debug|x86
|
||||
{24767C43-CD5A-4DC9-8D6B-429F255524E5}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{24767C43-CD5A-4DC9-8D6B-429F255524E5}.Release|ARM.Build.0 = Release|ARM
|
||||
{24767C43-CD5A-4DC9-8D6B-429F255524E5}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{24767C43-CD5A-4DC9-8D6B-429F255524E5}.Release|x64.ActiveCfg = Release|x64
|
||||
{24767C43-CD5A-4DC9-8D6B-429F255524E5}.Release|x64.Build.0 = Release|x64
|
||||
{24767C43-CD5A-4DC9-8D6B-429F255524E5}.Release|x86.ActiveCfg = Release|x86
|
||||
{24767C43-CD5A-4DC9-8D6B-429F255524E5}.Release|x86.Build.0 = Release|x86
|
||||
{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}.Debug|ARM64.Deploy.0 = Debug|ARM64
|
||||
{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}.Debug|x64.Build.0 = Debug|x64
|
||||
{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}.Debug|x86.Build.0 = Debug|Win32
|
||||
{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}.Debug|x86.Deploy.0 = Debug|Win32
|
||||
{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}.Release|ARM.Build.0 = Release|ARM
|
||||
{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}.Release|ARM64.Deploy.0 = Release|ARM64
|
||||
{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}.Release|x64.ActiveCfg = Release|x64
|
||||
{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}.Release|x64.Build.0 = Release|x64
|
||||
{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}.Release|x64.Deploy.0 = Release|x64
|
||||
{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}.Release|x86.ActiveCfg = Release|Win32
|
||||
{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}.Release|x86.Build.0 = Release|Win32
|
||||
{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}.Release|x86.Deploy.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {97D9888A-CF9F-4147-8CCE-71093C057452}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
BIN
internal/CalculatorUnitTests/Assets/LockScreenLogo.scale-200.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
internal/CalculatorUnitTests/Assets/SplashScreen.scale-200.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.2 KiB |
BIN
internal/CalculatorUnitTests/Assets/StoreLogo.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 3.1 KiB |
45
internal/CalculatorUnitTests/AsyncHelper.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "AsyncHelper.h"
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
using namespace std;
|
||||
using namespace concurrency;
|
||||
using namespace Platform;
|
||||
using namespace CalculatorApp;
|
||||
using namespace Windows::UI::Core;
|
||||
using namespace Windows::ApplicationModel::Core;
|
||||
|
||||
task<void> AsyncHelper::RunOnUIThreadAsync(function<void()>&& action)
|
||||
{
|
||||
auto callback = ref new DispatchedHandler([action]()
|
||||
{
|
||||
action();
|
||||
});
|
||||
|
||||
return create_task(CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(CoreDispatcherPriority::Normal, callback));
|
||||
}
|
||||
|
||||
void AsyncHelper::RunOnUIThread(function<void()>&& action, DWORD timeout)
|
||||
{
|
||||
task<void> waitTask = RunOnUIThreadAsync([action]()
|
||||
{
|
||||
action();
|
||||
});
|
||||
|
||||
WaitForTask<void>(waitTask, timeout);
|
||||
}
|
||||
|
||||
void AsyncHelper::Delay(DWORD milliseconds)
|
||||
{
|
||||
thread timer(bind(CalculatorApp::AsyncHelper::Sleep, milliseconds));
|
||||
timer.join();
|
||||
}
|
||||
|
||||
void AsyncHelper::Sleep(DWORD milliseconds)
|
||||
{
|
||||
this_thread::sleep_for(chrono::milliseconds(milliseconds));
|
||||
}
|
77
internal/CalculatorUnitTests/AsyncHelper.h
Normal file
@@ -0,0 +1,77 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
#include <wrl\wrappers\corewrappers.h>
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
class AsyncHelper
|
||||
{
|
||||
public:
|
||||
static concurrency::task<void> RunOnUIThreadAsync(std::function<void()>&& action);
|
||||
static void RunOnUIThread(std::function<void()>&& action, DWORD timeout = INFINITE);
|
||||
static void Delay(DWORD milliseconds);
|
||||
|
||||
template<typename T>
|
||||
static void RunOnUIThread(std::function<concurrency::task<T>()>&& action, DWORD timeout = INFINITE)
|
||||
{
|
||||
concurrency::task<T> t;
|
||||
concurrency::task<void> uiTask = RunOnUIThreadAsync([&t, action]()
|
||||
{
|
||||
t = action();
|
||||
}).then([&t]()
|
||||
{
|
||||
t.wait();
|
||||
}, concurrency::task_continuation_context::use_arbitrary());
|
||||
|
||||
WaitForTask<void>(uiTask, timeout);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static bool WaitForTask(concurrency::task<T>& t, DWORD timeout = INFINITE)
|
||||
{
|
||||
Microsoft::WRL::Wrappers::Event event(CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS));
|
||||
if (!event.IsValid())
|
||||
{
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
Platform::Exception^ ex;
|
||||
t.then([&event, &ex](concurrency::task<T> prevTask)
|
||||
{
|
||||
try
|
||||
{
|
||||
prevTask.get();
|
||||
}
|
||||
catch (Platform::Exception^ e)
|
||||
{
|
||||
ex = e;
|
||||
}
|
||||
|
||||
if (event.IsValid())
|
||||
{
|
||||
SetEvent(event.Get());
|
||||
}
|
||||
}, concurrency::task_continuation_context::use_arbitrary());
|
||||
|
||||
DWORD waitResult;// = STATUS_PENDING;
|
||||
waitResult = WaitForSingleObjectEx(event.Get(), timeout, true);
|
||||
event.Close();
|
||||
|
||||
if (ex != nullptr)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
|
||||
if (waitResult == WAIT_FAILED)
|
||||
{
|
||||
throw ref new Platform::Exception(-1, L"Error in waiting for task completion: " + waitResult.ToString());
|
||||
}
|
||||
|
||||
return waitResult == WAIT_OBJECT_0;
|
||||
}
|
||||
private:
|
||||
static void Sleep(DWORD milliseconds);
|
||||
};
|
||||
}
|
225
internal/CalculatorUnitTests/CalcEngineTests.cpp
Normal file
@@ -0,0 +1,225 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include <WexTestClass.h>
|
||||
|
||||
#include "CalcViewModel\Common\EngineResourceProvider.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace WEX::Common;
|
||||
using namespace WEX::Logging;
|
||||
using namespace WEX::TestExecution;
|
||||
|
||||
using namespace CalculatorApp;
|
||||
using namespace CalculationManager;
|
||||
|
||||
static constexpr size_t MAX_HISTORY_SIZE = 20;
|
||||
|
||||
namespace CalculatorUnitTests
|
||||
{
|
||||
class CalcEngineTests
|
||||
{
|
||||
TEST_CLASS(CalcEngineTests);
|
||||
TEST_CLASS_SETUP(CommonSetup)
|
||||
{
|
||||
m_resourceProvider = make_shared<EngineResourceProvider>();
|
||||
m_history = make_shared<CalculatorHistory>(CM_STD, MAX_HISTORY_SIZE);
|
||||
CCalcEngine::InitialOneTimeOnlySetup(*(m_resourceProvider.get()));
|
||||
m_calcEngine = make_unique<CCalcEngine>(false /* Respect Order of Operations */, false /* Set to Integer Mode */, m_resourceProvider.get(), nullptr, m_history);
|
||||
return true;
|
||||
}
|
||||
TEST_METHOD_CLEANUP(Cleanup)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST_METHOD(TestGroupDigitsPerRadix)
|
||||
{
|
||||
// Empty/Error cases
|
||||
VERIFY_IS_TRUE(m_calcEngine->GroupDigitsPerRadix(L"", 10).empty(), L"Verify grouping empty string returns empty string.");
|
||||
VERIFY_ARE_EQUAL(L"12345678", m_calcEngine->GroupDigitsPerRadix(L"12345678", 9), L"Verify grouping on invalid base returns original string");
|
||||
|
||||
// Octal
|
||||
VERIFY_ARE_EQUAL(L"1 234 567", m_calcEngine->GroupDigitsPerRadix(L"1234567", 8), L"Verify grouping in octal.");
|
||||
VERIFY_ARE_EQUAL(L"123", m_calcEngine->GroupDigitsPerRadix(L"123", 8), L"Verify minimum grouping in octal.");
|
||||
|
||||
// Binary/Hexadecimal
|
||||
VERIFY_ARE_EQUAL(L"12 3456 7890", m_calcEngine->GroupDigitsPerRadix(L"1234567890", 2), L"Verify grouping in binary.");
|
||||
VERIFY_ARE_EQUAL(L"1234", m_calcEngine->GroupDigitsPerRadix(L"1234", 2), L"Verify minimum grouping in binary.");
|
||||
VERIFY_ARE_EQUAL(L"12 3456 7890", m_calcEngine->GroupDigitsPerRadix(L"1234567890", 16), L"Verify grouping in hexadecimal.");
|
||||
VERIFY_ARE_EQUAL(L"1234", m_calcEngine->GroupDigitsPerRadix(L"1234", 16), L"Verify minimum grouping in hexadecimal.");
|
||||
|
||||
// Decimal
|
||||
VERIFY_ARE_EQUAL(L"1,234,567,890", m_calcEngine->GroupDigitsPerRadix(L"1234567890", 10), L"Verify grouping in base10.");
|
||||
VERIFY_ARE_EQUAL(L"1,234,567.89", m_calcEngine->GroupDigitsPerRadix(L"1234567.89", 10), L"Verify grouping in base10 with decimal.");
|
||||
VERIFY_ARE_EQUAL(L"1,234,567e89", m_calcEngine->GroupDigitsPerRadix(L"1234567e89", 10), L"Verify grouping in base10 with exponent.");
|
||||
VERIFY_ARE_EQUAL(L"1,234,567.89e5", m_calcEngine->GroupDigitsPerRadix(L"1234567.89e5", 10), L"Verify grouping in base10 with decimal and exponent.");
|
||||
VERIFY_ARE_EQUAL(L"-123,456,789", m_calcEngine->GroupDigitsPerRadix(L"-123456789", 10), L"Verify grouping in base10 with negative.");
|
||||
}
|
||||
|
||||
TEST_METHOD(TestIsNumberInvalid)
|
||||
{
|
||||
// Binary Number Checks
|
||||
vector<wstring> validBinStrs{ L"0", L"1", L"0011", L"1100" };
|
||||
vector<wstring> invalidBinStrs{ L"2", L"A", L"0.1" };
|
||||
for (wstring const& str : validBinStrs)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(0, m_calcEngine->IsNumberInvalid(str, 0, 0, 2 /* Binary */));
|
||||
}
|
||||
for (wstring const& str : invalidBinStrs)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(IDS_ERR_UNK_CH, m_calcEngine->IsNumberInvalid(str, 0, 0, 2 /* Binary */));
|
||||
}
|
||||
|
||||
// Octal Number Checks
|
||||
vector<wstring> validOctStrs{ L"0", L"7", L"01234567", L"76543210" };
|
||||
vector<wstring> invalidOctStrs{ L"8", L"A", L"0.7" };
|
||||
for (wstring const& str : validOctStrs)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(0, m_calcEngine->IsNumberInvalid(str, 0, 0, 8 /* Octal */));
|
||||
}
|
||||
for (wstring const& str : invalidOctStrs)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(IDS_ERR_UNK_CH, m_calcEngine->IsNumberInvalid(str, 0, 0, 8 /* Octal */));
|
||||
}
|
||||
|
||||
// Hexadecimal Number Checks
|
||||
vector<wstring> validHexStrs{ L"0", L"F", L"0123456789ABCDEF", L"FEDCBA9876543210" };
|
||||
vector<wstring> invalidHexStrs{ L"G", L"abcdef", L"x", L"0.1" };
|
||||
for (wstring const& str : validHexStrs)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(0, m_calcEngine->IsNumberInvalid(str, 0, 0, 16 /* HEx */));
|
||||
}
|
||||
for (wstring const& str : invalidHexStrs)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(IDS_ERR_UNK_CH, m_calcEngine->IsNumberInvalid(str, 0, 0, 16 /* Hex */));
|
||||
}
|
||||
|
||||
// Decimal Number Checks
|
||||
|
||||
// Special case errors: long exponent, long mantissa
|
||||
wstring longExp(L"1e12345");
|
||||
VERIFY_ARE_EQUAL(0, m_calcEngine->IsNumberInvalid(longExp, 5 /* Max exp length */, 100, 10 /* Decimal */));
|
||||
VERIFY_ARE_EQUAL(IDS_ERR_INPUT_OVERFLOW, m_calcEngine->IsNumberInvalid(longExp, 4 /* Max exp length */, 100, 10 /* Decimal */));
|
||||
// Mantissa length is sum of:
|
||||
// - digits before decimal separator, minus leading zeroes
|
||||
// - digits after decimal separator, including trailing zeroes
|
||||
// Each of these mantissa values should calculate as a length of 5
|
||||
vector<wstring> longMantStrs{ L"10000", L"10.000", L"0000012345", L"123.45", L"0.00123", L"0.12345", L"-123.45e678" };
|
||||
for (wstring const& str : longMantStrs)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(0, m_calcEngine->IsNumberInvalid(str, 100, 5 /* Max mantissa length */, 10 /* Decimal */));
|
||||
}
|
||||
for (wstring const& str : longMantStrs)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(IDS_ERR_INPUT_OVERFLOW, m_calcEngine->IsNumberInvalid(str, 100, 4 /* Max mantissa length */, 10 /* Decimal */));
|
||||
}
|
||||
|
||||
// Regex matching (descriptions taken from CalcUtils.cpp)
|
||||
// Use 100 for exp/mantissa length as they are tested above
|
||||
vector<wstring> validDecStrs{
|
||||
// Start with an optional + or -
|
||||
L"+1", L"-1", L"1",
|
||||
// Followed by zero or more digits
|
||||
L"-", L"", L"1234567890",
|
||||
// Followed by an optional decimal point
|
||||
L"1.0", L"-.", L"1.",
|
||||
// Followed by zero or more digits
|
||||
L"0.0", L"0.123456",
|
||||
// Followed by an optional exponent ('e')
|
||||
L"1e", L"1.e", L"-e",
|
||||
// If there's an exponent, its optionally followed by + or -
|
||||
// and followed by zero or more digits
|
||||
L"1e+12345", L"1e-12345", L"1e123",
|
||||
// All together
|
||||
L"-123.456e+789"
|
||||
};
|
||||
vector<wstring> invalidDecStrs{ L"x123", L"123-", L"1e1.2", L"1-e2" };
|
||||
for (wstring const& str : validDecStrs)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(0, m_calcEngine->IsNumberInvalid(str, 100, 100, 10 /* Dec */));
|
||||
}
|
||||
for (wstring const& str : invalidDecStrs)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(IDS_ERR_UNK_CH, m_calcEngine->IsNumberInvalid(str, 100, 100, 10 /* Dec */));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST_METHOD(TestDigitGroupingStringToGroupingVector)
|
||||
{
|
||||
vector<uint32_t> groupingVector{};
|
||||
VERIFY_ARE_EQUAL(groupingVector, CCalcEngine::DigitGroupingStringToGroupingVector(L""), L"Verify empty grouping");
|
||||
|
||||
groupingVector = { 1 };
|
||||
VERIFY_ARE_EQUAL(groupingVector, CCalcEngine::DigitGroupingStringToGroupingVector(L"1"), L"Verify simple grouping");
|
||||
|
||||
groupingVector = { 3, 0 };
|
||||
VERIFY_ARE_EQUAL(groupingVector, CCalcEngine::DigitGroupingStringToGroupingVector(L"3;0"), L"Verify standard grouping");
|
||||
|
||||
groupingVector = { 3, 0, 0 };
|
||||
VERIFY_ARE_EQUAL(groupingVector, CCalcEngine::DigitGroupingStringToGroupingVector(L"3;0;0"), L"Verify expanded non-repeating grouping");
|
||||
|
||||
groupingVector = { 5, 3, 2, 4, 6 };
|
||||
VERIFY_ARE_EQUAL(groupingVector, CCalcEngine::DigitGroupingStringToGroupingVector(L"5;3;2;4;6"), L"Verify long grouping");
|
||||
|
||||
groupingVector = { 15, 15, 15, 0 };
|
||||
VERIFY_ARE_EQUAL(groupingVector, CCalcEngine::DigitGroupingStringToGroupingVector(L"15;15;15;0"), L"Verify large grouping");
|
||||
|
||||
groupingVector = { 4, 7, 0 };
|
||||
VERIFY_ARE_EQUAL(groupingVector, CCalcEngine::DigitGroupingStringToGroupingVector(L"4;16;7;25;0"), L"Verify we ignore oversize grouping");
|
||||
}
|
||||
|
||||
TEST_METHOD(TestGroupDigits)
|
||||
{
|
||||
wstring result{ L"1234567" };
|
||||
VERIFY_ARE_EQUAL(result, m_calcEngine->GroupDigits(L"", { 3, 0 }, L"1234567", false), L"Verify handling of empty delimiter.");
|
||||
VERIFY_ARE_EQUAL(result, m_calcEngine->GroupDigits(L",", {}, L"1234567", false), L"Verify handling of empty grouping.");
|
||||
|
||||
result = L"1,234,567";
|
||||
VERIFY_ARE_EQUAL(result, m_calcEngine->GroupDigits(L",", { 3, 0 }, L"1234567", false), L"Verify standard digit grouping.");
|
||||
|
||||
result = L"1 234 567";
|
||||
VERIFY_ARE_EQUAL(result, m_calcEngine->GroupDigits(L" ", { 3, 0 }, L"1234567", false), L"Verify delimiter change.");
|
||||
|
||||
result = L"1|||234|||567";
|
||||
VERIFY_ARE_EQUAL(result, m_calcEngine->GroupDigits(L"|||", { 3, 0 }, L"1234567", false), L"Verify long delimiter.");
|
||||
|
||||
result = L"12,345e67";
|
||||
VERIFY_ARE_EQUAL(result, m_calcEngine->GroupDigits(L",", { 3, 0 }, L"12345e67", false), L"Verify respect of exponent.");
|
||||
|
||||
result = L"12,345.67";
|
||||
VERIFY_ARE_EQUAL(result, m_calcEngine->GroupDigits(L",", { 3, 0 }, L"12345.67", false), L"Verify respect of decimal.");
|
||||
|
||||
result = L"1,234.56e7";
|
||||
VERIFY_ARE_EQUAL(result, m_calcEngine->GroupDigits(L",", { 3, 0 }, L"1234.56e7", false), L"Verify respect of exponent and decimal.");
|
||||
|
||||
result = L"-1,234,567";
|
||||
VERIFY_ARE_EQUAL(result, m_calcEngine->GroupDigits(L",", { 3, 0 }, L"-1234567", true), L"Verify negative number grouping.");
|
||||
|
||||
// Test various groupings
|
||||
result = L"1234567890123456";
|
||||
VERIFY_ARE_EQUAL(result, m_calcEngine->GroupDigits(L",", { 0, 0 }, L"1234567890123456", false), L"Verify no grouping.");
|
||||
|
||||
result = L"1234567890123,456";
|
||||
VERIFY_ARE_EQUAL(result, m_calcEngine->GroupDigits(L",", { 3 }, L"1234567890123456", false), L"Verify non-repeating grouping.");
|
||||
VERIFY_ARE_EQUAL(result, m_calcEngine->GroupDigits(L",", { 3, 0, 0 }, L"1234567890123456", false), L"Verify expanded form non-repeating grouping.");
|
||||
|
||||
result = L"12,34,56,78,901,23456";
|
||||
VERIFY_ARE_EQUAL(result, m_calcEngine->GroupDigits(L",", { 5, 3, 2, 0 }, L"1234567890123456", false), L"Verify multigroup with repeating grouping.");
|
||||
|
||||
result = L"1234,5678,9012,3456";
|
||||
VERIFY_ARE_EQUAL(result, m_calcEngine->GroupDigits(L",", { 4, 0 }, L"1234567890123456", false), L"Verify repeating non-standard grouping.");
|
||||
|
||||
result = L"123456,78,901,23456";
|
||||
VERIFY_ARE_EQUAL(result, m_calcEngine->GroupDigits(L",", { 5, 3, 2 }, L"1234567890123456", false), L"Verify multigroup non-repeating grouping.");
|
||||
VERIFY_ARE_EQUAL(result, m_calcEngine->GroupDigits(L",", { 5, 3, 2, 0, 0 }, L"1234567890123456", false), L"Verify expanded form multigroup non-repeating grouping.");
|
||||
}
|
||||
|
||||
private:
|
||||
unique_ptr<CCalcEngine> m_calcEngine;
|
||||
shared_ptr<IResourceProvider> m_resourceProvider;
|
||||
shared_ptr<CalculatorHistory> m_history;
|
||||
};
|
||||
}
|
366
internal/CalculatorUnitTests/CalcInputTest.cpp
Normal file
@@ -0,0 +1,366 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include <WexTestClass.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace WEX::Common;
|
||||
using namespace WEX::Logging;
|
||||
using namespace WEX::TestExecution;
|
||||
|
||||
using namespace CalculationManager;
|
||||
|
||||
namespace CalculatorUnitTests
|
||||
{
|
||||
class CalcInputTest
|
||||
{
|
||||
TEST_CLASS(CalcInputTest);
|
||||
TEST_CLASS_SETUP(CommonSetup)
|
||||
{
|
||||
m_calcInput = CalcEngine::CalcInput(L'.');
|
||||
return true;
|
||||
}
|
||||
TEST_METHOD_CLEANUP(Cleanup)
|
||||
{
|
||||
m_calcInput.Clear();
|
||||
m_calcInput.SetDecimalSymbol(L'.');
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST_METHOD(Clear)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32);
|
||||
m_calcInput.TryToggleSign(false, L"999");
|
||||
m_calcInput.TryAddDecimalPt();
|
||||
m_calcInput.TryAddDigit(2, 10, false, L"999", 64, 32);
|
||||
m_calcInput.TryBeginExponent();
|
||||
m_calcInput.TryAddDigit(3, 10, false, L"999", 64, 32);
|
||||
|
||||
VERIFY_ARE_EQUAL(L"-1.2e+3", m_calcInput.ToString(10, false), L"Verify input is correct.");
|
||||
|
||||
m_calcInput.Clear();
|
||||
|
||||
::Log::Comment(m_calcInput.ToString(10, false).c_str());
|
||||
VERIFY_ARE_EQUAL(L"0", m_calcInput.ToString(10, false), L"Verify input is 0 after clear.");
|
||||
}
|
||||
|
||||
TEST_METHOD(TryToggleSignZero)
|
||||
{
|
||||
VERIFY_IS_TRUE(m_calcInput.TryToggleSign(false, L"999"), L"Verify toggling 0 succeeds.");
|
||||
VERIFY_ARE_EQUAL(L"0", m_calcInput.ToString(10, false), L"Verify toggling 0 does not create -0.");
|
||||
}
|
||||
TEST_METHOD(TryToggleSignExponent)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32);
|
||||
m_calcInput.TryBeginExponent();
|
||||
m_calcInput.TryAddDigit(2, 10, false, L"999", 64, 32);
|
||||
VERIFY_IS_TRUE(m_calcInput.TryToggleSign(false, L"999"), L"Verify toggling exponent sign succeeds.");
|
||||
VERIFY_ARE_EQUAL(L"1.e-2", m_calcInput.ToString(10, false), L"Verify toggling exponent sign does not toggle base sign.");
|
||||
VERIFY_IS_TRUE(m_calcInput.TryToggleSign(false, L"999"), L"Verify toggling exponent sign succeeds.");
|
||||
VERIFY_ARE_EQUAL(L"1.e+2", m_calcInput.ToString(10, false), L"Verify toggling negative exponent sign does not toggle base sign.");
|
||||
}
|
||||
TEST_METHOD(TryToggleSignBase)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32);
|
||||
VERIFY_IS_TRUE(m_calcInput.TryToggleSign(false, L"999"), L"Verify toggling base sign succeeds.");
|
||||
VERIFY_ARE_EQUAL(L"-1", m_calcInput.ToString(10, false), L"Verify toggling base sign creates negative base.");
|
||||
VERIFY_IS_TRUE(m_calcInput.TryToggleSign(false, L"999"), L"Verify toggling base sign succeeds.");
|
||||
VERIFY_ARE_EQUAL(L"1", m_calcInput.ToString(10, false), L"Verify toggling negative base sign creates positive base.");
|
||||
}
|
||||
TEST_METHOD(TryToggleSignBaseIntegerMode)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32);
|
||||
VERIFY_IS_TRUE(m_calcInput.TryToggleSign(true, L"999"), L"Verify toggling base sign in integer mode succeeds.");
|
||||
VERIFY_ARE_EQUAL(L"-1", m_calcInput.ToString(10, false), L"Verify toggling base sign creates negative base.");
|
||||
}
|
||||
TEST_METHOD(TryToggleSignRollover)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32);
|
||||
m_calcInput.TryAddDigit(2, 10, false, L"999", 64, 32);
|
||||
VERIFY_IS_TRUE(m_calcInput.TryToggleSign(true, L"127"), L"Verify toggling base sign in integer mode succeeds.");
|
||||
m_calcInput.TryAddDigit(8, 10, false, L"999", 64, 32);
|
||||
VERIFY_IS_FALSE(m_calcInput.TryToggleSign(true, L"127"), L"Verify toggling base sign in integer mode fails on rollover.");
|
||||
VERIFY_ARE_EQUAL(L"-128", m_calcInput.ToString(10, false), L"Verify toggling base sign on rollover does not change value.");
|
||||
}
|
||||
|
||||
TEST_METHOD(TryAddDigitLeadingZeroes)
|
||||
{
|
||||
VERIFY_IS_TRUE(m_calcInput.TryAddDigit(0, 10, false, L"999", 64, 32), L"Verify TryAddDigit succeeds.");
|
||||
VERIFY_IS_TRUE(m_calcInput.TryAddDigit(0, 10, false, L"999", 64, 32), L"Verify TryAddDigit succeeds.");
|
||||
VERIFY_IS_TRUE(m_calcInput.TryAddDigit(0, 10, false, L"999", 64, 32), L"Verify TryAddDigit succeeds.");
|
||||
VERIFY_ARE_EQUAL(L"0", m_calcInput.ToString(10, false), L"Verify leading zeroes are ignored.");
|
||||
}
|
||||
TEST_METHOD(TryAddDigitMaxCount)
|
||||
{
|
||||
VERIFY_IS_TRUE(m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32), L"Verify TryAddDigit for base with length < maxDigits succeeds.");
|
||||
VERIFY_ARE_EQUAL(L"1", m_calcInput.ToString(10, false), L"Verify adding digit for base with length < maxDigits succeeded.");
|
||||
VERIFY_IS_FALSE(m_calcInput.TryAddDigit(2, 10, false, L"999", 64, 1), L"Verify TryAddDigit for base with length > maxDigits fails.");
|
||||
VERIFY_ARE_EQUAL(L"1", m_calcInput.ToString(10, false), L"Verify digit for base was not added.");
|
||||
m_calcInput.TryBeginExponent();
|
||||
VERIFY_IS_TRUE(m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32), L"Verify TryAddDigit for exponent with length < maxDigits succeeds.");
|
||||
VERIFY_IS_TRUE(m_calcInput.TryAddDigit(2, 10, false, L"999", 64, 32), L"Verify TryAddDigit for exponent with length < maxDigits succeeds.");
|
||||
VERIFY_IS_TRUE(m_calcInput.TryAddDigit(3, 10, false, L"999", 64, 32), L"Verify TryAddDigit for exponent with length < maxDigits succeeds.");
|
||||
VERIFY_IS_TRUE(m_calcInput.TryAddDigit(4, 10, false, L"999", 64, 32), L"Verify TryAddDigit for exponent with length < maxDigits succeeds.");
|
||||
VERIFY_IS_FALSE(m_calcInput.TryAddDigit(5, 10, false, L"999", 64, 32), L"Verify TryAddDigit for exponent with length > maxDigits fails.");
|
||||
VERIFY_ARE_EQUAL(L"1.e+1234", m_calcInput.ToString(10, false), L"Verify adding digits for exponent with length < maxDigits succeeded.");
|
||||
|
||||
m_calcInput.Clear();
|
||||
m_calcInput.TryAddDecimalPt();
|
||||
VERIFY_IS_TRUE(m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 1), L"Verify decimal point and leading zero does not count toward maxDigits.");
|
||||
VERIFY_ARE_EQUAL(L"0.1", m_calcInput.ToString(10, false), L"Verify input value checking dec pt and leading zero impact on maxDigits.");
|
||||
}
|
||||
TEST_METHOD(TryAddDigitValues)
|
||||
{
|
||||
// Use an arbitrary value > 16 to test that input accepts digits > hexadecimal 0xF.
|
||||
// TryAddDigit does not validate whether the digit fits within the current radix.
|
||||
for (unsigned int i = 0; i < 25; i++)
|
||||
{
|
||||
VERIFY_IS_TRUE(m_calcInput.TryAddDigit(i, 10, false, L"999", 64, 32), String().Format(L"Verify TryAddDigit succeeds for %d", i));
|
||||
m_calcInput.Clear();
|
||||
}
|
||||
}
|
||||
TEST_METHOD(TryAddDigitRolloverBaseCheck)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32);
|
||||
VERIFY_IS_FALSE(m_calcInput.TryAddDigit(2, 16, true, L"999", 64, 1), L"Verify TryAddDigit rollover fails for bases other than 8,10.");
|
||||
VERIFY_IS_FALSE(m_calcInput.TryAddDigit(1, 2, true, L"999", 64, 1), L"Verify TryAddDigit rollover fails for bases other than 8,10.");
|
||||
}
|
||||
TEST_METHOD(TryAddDigitRolloverOctalByte)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 8, true, L"777", 64, 32);
|
||||
VERIFY_IS_TRUE(m_calcInput.TryAddDigit(2, 8, true, L"377", 8, 1), L"Verify we can add an extra digit in OctalByte if first digit <= 3.");
|
||||
|
||||
m_calcInput.Clear();
|
||||
m_calcInput.TryAddDigit(4, 8, true, L"777", 64, 32);
|
||||
VERIFY_IS_FALSE(m_calcInput.TryAddDigit(2, 8, true, L"377", 8, 1), L"Verify we cannot add an extra digit in OctalByte if first digit > 3.");
|
||||
}
|
||||
TEST_METHOD(TryAddDigitRolloverOctalWord)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 8, true, L"777", 64, 32);
|
||||
VERIFY_IS_TRUE(m_calcInput.TryAddDigit(2, 8, true, L"377", 16, 1), L"Verify we can add an extra digit in OctalByte if first digit == 1.");
|
||||
|
||||
m_calcInput.Clear();
|
||||
m_calcInput.TryAddDigit(2, 8, true, L"777", 64, 32);
|
||||
VERIFY_IS_FALSE(m_calcInput.TryAddDigit(2, 8, true, L"377", 16, 1), L"Verify we cannot add an extra digit in OctalByte if first digit > 1.");
|
||||
}
|
||||
TEST_METHOD(TryAddDigitRolloverOctalDword)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 8, true, L"777", 64, 32);
|
||||
VERIFY_IS_TRUE(m_calcInput.TryAddDigit(2, 8, true, L"377", 32, 1), L"Verify we can add an extra digit in OctalByte if first digit <= 3.");
|
||||
|
||||
m_calcInput.Clear();
|
||||
m_calcInput.TryAddDigit(4, 8, true, L"777", 64, 32);
|
||||
VERIFY_IS_FALSE(m_calcInput.TryAddDigit(2, 8, true, L"377", 32, 1), L"Verify we cannot add an extra digit in OctalByte if first digit > 3.");
|
||||
}
|
||||
TEST_METHOD(TryAddDigitRolloverOctalQword)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 8, true, L"777", 64, 32);
|
||||
VERIFY_IS_TRUE(m_calcInput.TryAddDigit(2, 8, true, L"377", 64, 1), L"Verify we can add an extra digit in OctalByte if first digit == 1.");
|
||||
|
||||
m_calcInput.Clear();
|
||||
m_calcInput.TryAddDigit(2, 8, true, L"777", 64, 32);
|
||||
VERIFY_IS_FALSE(m_calcInput.TryAddDigit(2, 8, true, L"377", 64, 1), L"Verify we cannot add an extra digit in OctalByte if first digit > 1.");
|
||||
}
|
||||
TEST_METHOD(TryAddDigitRolloverDecimal)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 10, true, L"127", 64, 32);
|
||||
VERIFY_IS_FALSE(m_calcInput.TryAddDigit(0, 10, true, L"1", 8, 1), L"Verify we cannot add a digit if input size matches maxStr size.");
|
||||
m_calcInput.TryAddDigit(2, 10, true, L"127", 64, 32);
|
||||
VERIFY_IS_FALSE(m_calcInput.TryAddDigit(2, 10, true, L"110", 8, 2), L"Verify we cannot add a digit if n char comparison > 0.");
|
||||
VERIFY_IS_TRUE(m_calcInput.TryAddDigit(7, 10, true, L"130", 8, 2), L"Verify we can add a digit if n char comparison < 0.");
|
||||
|
||||
m_calcInput.Clear();
|
||||
m_calcInput.TryAddDigit(1, 10, true, L"127", 64, 32);
|
||||
m_calcInput.TryAddDigit(2, 10, true, L"127", 64, 32);
|
||||
VERIFY_IS_FALSE(m_calcInput.TryAddDigit(8, 10, true, L"127", 8, 2), L"Verify we cannot add a digit if digit exceeds max value.");
|
||||
VERIFY_IS_TRUE(m_calcInput.TryAddDigit(7, 10, true, L"127", 8, 2), L"Verify we can add a digit if digit does not exceed max value.");
|
||||
|
||||
m_calcInput.Backspace();
|
||||
m_calcInput.TryToggleSign(true, L"127");
|
||||
VERIFY_IS_FALSE(m_calcInput.TryAddDigit(9, 10, true, L"127", 8, 2), L"Negative value: verify we cannot add a digit if digit exceeds max value.");
|
||||
VERIFY_IS_TRUE(m_calcInput.TryAddDigit(8, 10, true, L"127", 8, 2), L"Negative value: verify we can add a digit if digit does not exceed max value.");
|
||||
}
|
||||
|
||||
TEST_METHOD(TryAddDecimalPtEmpty)
|
||||
{
|
||||
VERIFY_IS_FALSE(m_calcInput.HasDecimalPt(), L"Verify input has no decimal point.");
|
||||
VERIFY_IS_TRUE(m_calcInput.TryAddDecimalPt(), L"Verify adding decimal to empty input.");
|
||||
VERIFY_IS_TRUE(m_calcInput.HasDecimalPt(), L"Verify input has decimal point.");
|
||||
VERIFY_ARE_EQUAL(L"0.", m_calcInput.ToString(10, false), L"Verify decimal on empty input.");
|
||||
}
|
||||
TEST_METHOD(TryAddDecimalPointTwice)
|
||||
{
|
||||
VERIFY_IS_FALSE(m_calcInput.HasDecimalPt(), L"Verify input has no decimal point.");
|
||||
VERIFY_IS_TRUE(m_calcInput.TryAddDecimalPt(), L"Verify adding decimal to empty input.");
|
||||
VERIFY_IS_TRUE(m_calcInput.HasDecimalPt(), L"Verify input has decimal point.");
|
||||
VERIFY_IS_FALSE(m_calcInput.TryAddDecimalPt(), L"Verify adding decimal point fails if input has decimal point.");
|
||||
}
|
||||
TEST_METHOD(TryAddDecimalPointExponent)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32);
|
||||
m_calcInput.TryBeginExponent();
|
||||
m_calcInput.TryAddDigit(2, 10, false, L"999", 64, 32);
|
||||
VERIFY_IS_FALSE(m_calcInput.TryAddDecimalPt(), L"Verify adding decimal point fails if input has exponent.");
|
||||
}
|
||||
|
||||
TEST_METHOD(TryBeginExponentNoExponent)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32);
|
||||
VERIFY_IS_TRUE(m_calcInput.TryBeginExponent(), L"Verify adding exponent succeeds on input without exponent.");
|
||||
VERIFY_ARE_EQUAL(L"1.e+0", m_calcInput.ToString(10, false), L"Verify exponent present.");
|
||||
}
|
||||
TEST_METHOD(TryBeginExponentWithExponent)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32);
|
||||
VERIFY_IS_TRUE(m_calcInput.TryBeginExponent(), L"Verify adding exponent succeeds on input without exponent.");
|
||||
VERIFY_IS_FALSE(m_calcInput.TryBeginExponent(), L"Verify cannot add exponent if input already has exponent.");
|
||||
}
|
||||
|
||||
TEST_METHOD(BackspaceZero)
|
||||
{
|
||||
m_calcInput.Backspace();
|
||||
VERIFY_ARE_EQUAL(L"0", m_calcInput.ToString(10, false), L"Verify backspace on 0 is still 0.");
|
||||
}
|
||||
TEST_METHOD(BackspaceSingleChar)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32);
|
||||
VERIFY_ARE_EQUAL(L"1", m_calcInput.ToString(10, false), L"Verify input before backspace.");
|
||||
m_calcInput.Backspace();
|
||||
VERIFY_ARE_EQUAL(L"0", m_calcInput.ToString(10, false), L"Verify input after backspace.");
|
||||
}
|
||||
TEST_METHOD(BackspaceMultiChar)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32);
|
||||
m_calcInput.TryAddDigit(2, 10, false, L"999", 64, 32);
|
||||
VERIFY_ARE_EQUAL(L"12", m_calcInput.ToString(10, false), L"Verify input before backspace.");
|
||||
m_calcInput.Backspace();
|
||||
VERIFY_ARE_EQUAL(L"1", m_calcInput.ToString(10, false), L"Verify input after backspace.");
|
||||
}
|
||||
TEST_METHOD(BackspaceDecimal)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32);
|
||||
m_calcInput.TryAddDecimalPt();
|
||||
VERIFY_ARE_EQUAL(L"1.", m_calcInput.ToString(10, false), L"Verify input before backspace.");
|
||||
VERIFY_IS_TRUE(m_calcInput.HasDecimalPt(), L"Verify input has decimal point.");
|
||||
m_calcInput.Backspace();
|
||||
VERIFY_ARE_EQUAL(L"1", m_calcInput.ToString(10, false), L"Verify input after backspace.");
|
||||
VERIFY_IS_FALSE(m_calcInput.HasDecimalPt(), L"Verify decimal point was removed.");
|
||||
}
|
||||
TEST_METHOD(BackspaceMultiCharDecimal)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32);
|
||||
m_calcInput.TryAddDecimalPt();
|
||||
m_calcInput.TryAddDigit(2, 10, false, L"999", 64, 32);
|
||||
m_calcInput.TryAddDigit(3, 10, false, L"999", 64, 32);
|
||||
VERIFY_ARE_EQUAL(L"1.23", m_calcInput.ToString(10, false), L"Verify input before backspace.");
|
||||
m_calcInput.Backspace();
|
||||
VERIFY_ARE_EQUAL(L"1.2", m_calcInput.ToString(10, false), L"Verify input after backspace.");
|
||||
}
|
||||
|
||||
TEST_METHOD(SetDecimalSymbol)
|
||||
{
|
||||
m_calcInput.TryAddDecimalPt();
|
||||
VERIFY_ARE_EQUAL(L"0.", m_calcInput.ToString(10, false), L"Verify default decimal point.");
|
||||
m_calcInput.SetDecimalSymbol(L',');
|
||||
VERIFY_ARE_EQUAL(L"0,", m_calcInput.ToString(10, false), L"Verify new decimal point.");
|
||||
}
|
||||
|
||||
TEST_METHOD(ToStringEmpty)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(L"0", m_calcInput.ToString(10, false), L"Verify ToString of empty value.");
|
||||
}
|
||||
TEST_METHOD(ToStringNegative)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32);
|
||||
m_calcInput.TryToggleSign(false, L"999");
|
||||
VERIFY_ARE_EQUAL(L"-1", m_calcInput.ToString(10, false), L"Verify ToString of negative value.");
|
||||
}
|
||||
TEST_METHOD(ToStringExponentBase10)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32);
|
||||
m_calcInput.TryBeginExponent();
|
||||
VERIFY_ARE_EQUAL(L"1.e+0", m_calcInput.ToString(10, false), L"Verify ToString of empty base10 exponent.");
|
||||
}
|
||||
TEST_METHOD(ToStringExponentBase8)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32);
|
||||
m_calcInput.TryBeginExponent();
|
||||
VERIFY_ARE_EQUAL(L"1.^+0", m_calcInput.ToString(8, false), L"Verify ToString of empty base8 exponent.");
|
||||
}
|
||||
TEST_METHOD(ToStringExponentNegative)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 8, false, L"999", 64, 32);
|
||||
m_calcInput.TryBeginExponent();
|
||||
m_calcInput.TryToggleSign(false, L"999");
|
||||
VERIFY_ARE_EQUAL(L"1.e-0", m_calcInput.ToString(10, false), L"Verify ToString of empty negative exponent.");
|
||||
}
|
||||
TEST_METHOD(ToStringExponentPositive)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32);
|
||||
m_calcInput.TryBeginExponent();
|
||||
m_calcInput.TryAddDigit(2, 10, false, L"999", 64, 32);
|
||||
m_calcInput.TryAddDigit(3, 10, false, L"999", 64, 32);
|
||||
m_calcInput.TryAddDigit(4, 10, false, L"999", 64, 32);
|
||||
VERIFY_ARE_EQUAL(L"1.e+234", m_calcInput.ToString(10, false), L"Verify ToString of exponent with value.");
|
||||
}
|
||||
TEST_METHOD(ToStringInteger)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32);
|
||||
VERIFY_ARE_EQUAL(L"1", m_calcInput.ToString(10, true), L"Verify ToString of integer value hides decimal.");
|
||||
}
|
||||
TEST_METHOD(ToStringBaseTooLong)
|
||||
{
|
||||
wstring maxStr{};
|
||||
for (size_t i = 0; i < MAX_STRLEN + 1; i++)
|
||||
{
|
||||
maxStr += L"1";
|
||||
m_calcInput.TryAddDigit(1, 10, false, maxStr, 64, 100);
|
||||
}
|
||||
auto result = m_calcInput.ToString(10, false);
|
||||
VERIFY_IS_TRUE(result.empty(), L"Verify ToString of base value that is too large yields empty string.");
|
||||
}
|
||||
TEST_METHOD(ToStringExponentTooLong)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32);
|
||||
m_calcInput.TryBeginExponent();
|
||||
wstring maxStr{L"11"};
|
||||
bool exponentCapped = false;
|
||||
for (size_t i = 0; i < MAX_STRLEN + 1; i++)
|
||||
{
|
||||
maxStr += L"1";
|
||||
if (!m_calcInput.TryAddDigit(1, 10, false, maxStr, 64, MAX_STRLEN + 25))
|
||||
{
|
||||
exponentCapped = true;
|
||||
}
|
||||
}
|
||||
auto result = m_calcInput.ToString(10, false);
|
||||
|
||||
// TryAddDigit caps the exponent length to C_EXP_MAX_DIGITS = 4, so ToString() succeeds.
|
||||
// If that cap is removed, ToString() should return an empty string.
|
||||
if (exponentCapped)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(L"1.e+1111", result, L"Verify ToString succeeds; exponent length is capped at C_EXP_MAX_DIGITS.");
|
||||
}
|
||||
else
|
||||
{
|
||||
VERIFY_IS_TRUE(result.empty(), L"Verify ToString of exponent value that is too large yields empty string.");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_METHOD(ToRational)
|
||||
{
|
||||
m_calcInput.TryAddDigit(1, 10, false, L"999", 64, 32);
|
||||
m_calcInput.TryAddDigit(2, 10, false, L"999", 64, 32);
|
||||
m_calcInput.TryAddDigit(3, 10, false, L"999", 64, 32);
|
||||
VERIFY_ARE_EQUAL(L"123", m_calcInput.ToString(10, false), L"Verify input before conversion to rational.");
|
||||
|
||||
auto rat = m_calcInput.ToRational(10, false);
|
||||
VERIFY_ARE_EQUAL(1, rat.P().Mantissa().size(), L"Verify digit count of rational.");
|
||||
VERIFY_ARE_EQUAL(123, rat.P().Mantissa().front(), L"Verify first digit of mantissa.");
|
||||
}
|
||||
|
||||
private:
|
||||
CalcEngine::CalcInput m_calcInput;
|
||||
};
|
||||
}
|
1123
internal/CalculatorUnitTests/CalculatorManagerTest.cpp
Normal file
365
internal/CalculatorUnitTests/CalculatorUnitTests.vcxproj
Normal file
@@ -0,0 +1,365 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\packages\Taef.Native.UWP.10.34.181220007\build\native\Taef.Native.UWP.props" Condition="Exists('..\..\packages\Taef.Native.UWP.10.34.181220007\build\native\Taef.Native.UWP.props')" />
|
||||
<Import Project="..\..\packages\Taef.Native.10.34.181220007\build\native\Taef.Native.props" Condition="Exists('..\..\packages\Taef.Native.10.34.181220007\build\native\Taef.Native.props')" />
|
||||
<Import Project="..\..\packages\Microsoft.TestInfrastructure.UniversalTest.1.0.20181107.1\build\Microsoft.TestInfrastructure.UniversalTest.props" Condition="Exists('..\..\packages\Microsoft.TestInfrastructure.UniversalTest.1.0.20181107.1\build\Microsoft.TestInfrastructure.UniversalTest.props')" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{E527A1F4-6B63-4DD0-B540-B8C06CFC3AFE}</ProjectGuid>
|
||||
<RootNamespace>CalculatorUnitTests</RootNamespace>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<MinimumVisualStudioVersion>15.0</MinimumVisualStudioVersion>
|
||||
<AppContainerApplication>true</AppContainerApplication>
|
||||
<ApplicationType>Windows Store</ApplicationType>
|
||||
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">10.0.17763.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformMinVersion>10.0.17134.0</WindowsTargetPlatformMinVersion>
|
||||
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
|
||||
<AppxPackageName>CalculatorUnitTests</AppxPackageName>
|
||||
<!-- We want to automatic replace of MinVersion/MaxVersionTested for unit tests. -->
|
||||
<AppxOSMinVersionReplaceManifestVersion>true</AppxOSMinVersionReplaceManifestVersion>
|
||||
<AppxOSMaxVersionTestedReplaceManifestVersion>true</AppxOSMaxVersionTestedReplaceManifestVersion>
|
||||
<!-- Needed to build the testmd package -->
|
||||
<GenerateAppxPackageOnBuild>true</GenerateAppxPackageOnBuild>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<!-- This has to be exactly in this place for this to work -->
|
||||
<PropertyGroup>
|
||||
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<IgnoreImportLibrary>true</IgnoreImportLibrary>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<IgnoreImportLibrary>true</IgnoreImportLibrary>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<IgnoreImportLibrary>true</IgnoreImportLibrary>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<IgnoreImportLibrary>true</IgnoreImportLibrary>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<IgnoreImportLibrary>true</IgnoreImportLibrary>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<IgnoreImportLibrary>true</IgnoreImportLibrary>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<IgnoreImportLibrary>true</IgnoreImportLibrary>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IgnoreImportLibrary>true</IgnoreImportLibrary>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros">
|
||||
<PackageCertificateKeyFile>TemporaryKey.pfx</PackageCertificateKeyFile>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/bigobj /await /std:c++17 /permissive- /Zc:twoPhase- %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;$(SolutionDir)..\src\CalcManager;$(SolutionDir)..\src\CalcViewModel;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/bigobj /await /std:c++17 /permissive- /Zc:twoPhase- %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;$(SolutionDir)..\src\CalcManager;$(SolutionDir)..\src\CalcViewModel;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/bigobj /await /std:c++17 /permissive- /Zc:twoPhase- %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;$(SolutionDir)..\src\CalcManager;$(SolutionDir)..\src\CalcViewModel;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/bigobj /await /std:c++17 /permissive- /Zc:twoPhase- %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;$(SolutionDir)..\src\CalcManager;$(SolutionDir)..\src\CalcViewModel;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/bigobj /await /std:c++17 /permissive- /Zc:twoPhase- %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;$(SolutionDir)..\src\CalcManager;$(SolutionDir)..\src\CalcViewModel;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/bigobj /await /std:c++17 /permissive- /Zc:twoPhase- %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;$(SolutionDir)..\src\CalcManager;$(SolutionDir)..\src\CalcViewModel;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/bigobj /await /std:c++17 /permissive- /Zc:twoPhase- %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;$(SolutionDir)..\src\CalcManager;$(SolutionDir)..\src\CalcViewModel;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/bigobj /await /std:c++17 /permissive- /Zc:twoPhase- %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;$(SolutionDir)..\src\CalcManager;$(SolutionDir)..\src\CalcViewModel;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="CalcEngineTests.cpp" />
|
||||
<ClCompile Include="CalcInputTest.cpp" />
|
||||
<ClCompile Include="CalculatorManagerTest.cpp" />
|
||||
<ClCompile Include="CurrencyConverterUnitTests.cpp" />
|
||||
<ClCompile Include="Mocks\CurrencyHttpClient.cpp" />
|
||||
<ClCompile Include="Module.cpp" />
|
||||
<ClCompile Include="NavCategoryUnitTests.cpp" />
|
||||
<ClCompile Include="UnitConverterTest.cpp" />
|
||||
<ClCompile Include="UtilsTests.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AsyncHelper.h" />
|
||||
<ClInclude Include="DateUtils.h" />
|
||||
<ClInclude Include="Helpers.h" />
|
||||
<ClInclude Include="Mocks\CurrencyHttpClient.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="UnitConverterViewModelUnitTests.h" />
|
||||
<ClInclude Include="UnitTestApp.xaml.h">
|
||||
<DependentUpon>UnitTestApp.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="UnitTestApp.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AppxManifest Include="Package.appxmanifest">
|
||||
<SubType>Designer</SubType>
|
||||
</AppxManifest>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="Assets\LockScreenLogo.scale-200.png" />
|
||||
<Image Include="Assets\SplashScreen.scale-200.png" />
|
||||
<Image Include="Assets\Square44x44Logo.scale-200.png" />
|
||||
<Image Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
|
||||
<Image Include="Assets\Square150x150Logo.scale-200.png" />
|
||||
<Image Include="Assets\StoreLogo.png" />
|
||||
<Image Include="Assets\Wide310x150Logo.scale-200.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="AsyncHelper.cpp" />
|
||||
<ClCompile Include="CopyPasteManagerTest.cpp" />
|
||||
<ClCompile Include="DateCalculatorUnitTests.cpp" />
|
||||
<ClCompile Include="HistoryTests.cpp" />
|
||||
<ClCompile Include="MultiWindowUnitTests.cpp" />
|
||||
<ClCompile Include="StandardViewModelUnitTests.cpp" />
|
||||
<ClCompile Include="UnitConverterViewModelUnitTests.cpp" />
|
||||
<ClCompile Include="UnitTestApp.xaml.cpp">
|
||||
<DependentUpon>UnitTestApp.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Xml Include="UnitTestApp.rd.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="TemporaryKey.pfx" />
|
||||
<None Include="testmd.definition" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PRIResource Include="..\..\src\Calculator\Resources\en-US\CEngineStrings.resw" />
|
||||
<PRIResource Include="..\..\src\Calculator\Resources\en-US\Resources.resw" />
|
||||
<PRIResource Include="Test.resw" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\CalcManager\CalcManager.vcxproj">
|
||||
<Project>{311e866d-8b93-4609-a691-265941fee101}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\src\CalcViewModel\CalcViewModel.vcxproj">
|
||||
<Project>{90e9761d-9262-4773-942d-caeae75d7140}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<!-- Append the manifest version to the custom macros as we use this in the testmd.definition file. -->
|
||||
<Target Name="AppendUniversalTestCustomMacros" DependsOnTargets="_CreateTestLayout" BeforeTargets="BuildUniversalTest">
|
||||
<PropertyGroup>
|
||||
<UniversalTestCustomMacros Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(UniversalTestCustomMacros)AppxPackageVCLibsDependency=$(AppxPackageTestDir)Dependencies\x86\Microsoft.VCLibs.x86.Debug.14.00.appx;</UniversalTestCustomMacros>
|
||||
<UniversalTestCustomMacros Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(UniversalTestCustomMacros)AppxPackageVCLibsDependency=$(AppxPackageTestDir)Dependencies\x86\Microsoft.VCLibs.x86.14.00.appx;</UniversalTestCustomMacros>
|
||||
<UniversalTestCustomMacros Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(UniversalTestCustomMacros)AppxPackageVCLibsDependency=$(AppxPackageTestDir)Dependencies\x64\Microsoft.VCLibs.x64.Debug.14.00.appx;</UniversalTestCustomMacros>
|
||||
<UniversalTestCustomMacros Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(UniversalTestCustomMacros)AppxPackageVCLibsDependency=$(AppxPackageTestDir)Dependencies\x64\Microsoft.VCLibs.x64.14.00.appx;</UniversalTestCustomMacros>
|
||||
<UniversalTestCustomMacros Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">$(UniversalTestCustomMacros)AppxPackageVCLibsDependency=$(AppxPackageTestDir)Dependencies\ARM\Microsoft.VCLibs.arm.Debug.14.00.appx;</UniversalTestCustomMacros>
|
||||
<UniversalTestCustomMacros Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">$(UniversalTestCustomMacros)AppxPackageVCLibsDependency=$(AppxPackageTestDir)Dependencies\ARM64\Microsoft.VCLibs.arm64.Debug.14.00.appx;</UniversalTestCustomMacros>
|
||||
<UniversalTestCustomMacros Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">$(UniversalTestCustomMacros)AppxPackageVCLibsDependency=$(AppxPackageTestDir)Dependencies\ARM\Microsoft.VCLibs.arm.14.00.appx;</UniversalTestCustomMacros>
|
||||
<UniversalTestCustomMacros Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">$(UniversalTestCustomMacros)AppxPackageVCLibsDependency=$(AppxPackageTestDir)Dependencies\ARM64\Microsoft.VCLibs.arm64.14.00.appx;</UniversalTestCustomMacros>
|
||||
<UniversalTestCustomMacros>$(UniversalTestCustomMacros)AppxPackagePublicKeyFile=$(AppxPackagePublicKeyFile);AppxPackageOutput=$(AppxPackageOutput);</UniversalTestCustomMacros>
|
||||
</PropertyGroup>
|
||||
</Target>
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\packages\Microsoft.TestInfrastructure.UniversalTest.1.0.20181107.1\build\Microsoft.TestInfrastructure.UniversalTest.targets" Condition="Exists('..\..\packages\Microsoft.TestInfrastructure.UniversalTest.1.0.20181107.1\build\Microsoft.TestInfrastructure.UniversalTest.targets')" />
|
||||
<Import Project="..\..\packages\Taef.Native.10.34.181220007\build\native\Taef.Native.targets" Condition="Exists('..\..\packages\Taef.Native.10.34.181220007\build\native\Taef.Native.targets')" />
|
||||
<Import Project="..\..\packages\Taef.Native.UWP.10.34.181220007\build\native\Taef.Native.UWP.targets" Condition="Exists('..\..\packages\Taef.Native.UWP.10.34.181220007\build\native\Taef.Native.UWP.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.TestInfrastructure.UniversalTest.1.0.20181107.1\build\Microsoft.TestInfrastructure.UniversalTest.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.TestInfrastructure.UniversalTest.1.0.20181107.1\build\Microsoft.TestInfrastructure.UniversalTest.props'))" />
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.TestInfrastructure.UniversalTest.1.0.20181107.1\build\Microsoft.TestInfrastructure.UniversalTest.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.TestInfrastructure.UniversalTest.1.0.20181107.1\build\Microsoft.TestInfrastructure.UniversalTest.targets'))" />
|
||||
<Error Condition="!Exists('..\..\packages\Taef.Native.10.34.181220007\build\native\Taef.Native.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Taef.Native.10.34.181220007\build\native\Taef.Native.props'))" />
|
||||
<Error Condition="!Exists('..\..\packages\Taef.Native.10.34.181220007\build\native\Taef.Native.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Taef.Native.10.34.181220007\build\native\Taef.Native.targets'))" />
|
||||
<Error Condition="!Exists('..\..\packages\Taef.Native.UWP.10.34.181220007\build\native\Taef.Native.UWP.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Taef.Native.UWP.10.34.181220007\build\native\Taef.Native.UWP.props'))" />
|
||||
<Error Condition="!Exists('..\..\packages\Taef.Native.UWP.10.34.181220007\build\native\Taef.Native.UWP.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Taef.Native.UWP.10.34.181220007\build\native\Taef.Native.UWP.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
102
internal/CalculatorUnitTests/CalculatorUnitTests.vcxproj.filters
Normal file
@@ -0,0 +1,102 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="UnitTestApp.xaml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PRIResource Include="Test.resw" />
|
||||
<PRIResource Include="..\..\src\Calculator\Resources\en-US\CEngineStrings.resw" />
|
||||
<PRIResource Include="..\..\src\Calculator\Resources\en-US\Resources.resw" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="CalculatorManagerTest.cpp" />
|
||||
<ClCompile Include="CurrencyConverterUnitTests.cpp" />
|
||||
<ClCompile Include="Mocks\CurrencyHttpClient.cpp" />
|
||||
<ClCompile Include="NavCategoryUnitTests.cpp" />
|
||||
<ClCompile Include="UnitConverterTest.cpp" />
|
||||
<ClCompile Include="UtilsTests.cpp" />
|
||||
<ClCompile Include="AsyncHelper.cpp" />
|
||||
<ClCompile Include="CopyPasteManagerTest.cpp" />
|
||||
<ClCompile Include="DateCalculatorUnitTests.cpp" />
|
||||
<ClCompile Include="HistoryTests.cpp" />
|
||||
<ClCompile Include="MultiWindowUnitTests.cpp" />
|
||||
<ClCompile Include="StandardViewModelUnitTests.cpp" />
|
||||
<ClCompile Include="UnitConverterViewModelUnitTests.cpp" />
|
||||
<ClCompile Include="UnitTestApp.xaml.cpp" />
|
||||
<ClCompile Include="pch.cpp" />
|
||||
<ClCompile Include="Module.cpp" />
|
||||
<ClCompile Include="CalcInputTest.cpp" />
|
||||
<ClCompile Include="CalcEngineTests.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AsyncHelper.h" />
|
||||
<ClInclude Include="DateUtils.h" />
|
||||
<ClInclude Include="Helpers.h" />
|
||||
<ClInclude Include="Mocks\CurrencyHttpClient.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="UnitConverterViewModelUnitTests.h" />
|
||||
<ClInclude Include="UnitTestApp.xaml.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Xml Include="UnitTestApp.rd.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="Assets\LockScreenLogo.scale-200.png" />
|
||||
<Image Include="Assets\SplashScreen.scale-200.png" />
|
||||
<Image Include="Assets\Square44x44Logo.scale-200.png" />
|
||||
<Image Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
|
||||
<Image Include="Assets\Square150x150Logo.scale-200.png" />
|
||||
<Image Include="Assets\StoreLogo.png" />
|
||||
<Image Include="Assets\Wide310x150Logo.scale-200.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AppxManifest Include="Package.appxmanifest" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="TemporaryKey.pfx" />
|
||||
<None Include="testmd.definition" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
<None Include="$(MSBuildThisFileDirectory)\$(Platform)\*.dll" />
|
||||
</ItemGroup>
|
||||
</Project>
|
602
internal/CalculatorUnitTests/CopyPasteManagerTest.cpp
Normal file
@@ -0,0 +1,602 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include <WexTestClass.h>
|
||||
|
||||
#include "CalcViewModel\StandardCalculatorViewModel.h"
|
||||
#include "CalcViewModel\Common\CopyPasteManager.h"
|
||||
|
||||
using namespace CalculationManager;
|
||||
using namespace CalculatorApp;
|
||||
using namespace CalculatorApp::Common;
|
||||
using namespace CalculatorApp::ViewModel;
|
||||
using namespace Platform;
|
||||
using namespace std;
|
||||
using namespace WEX::Logging;
|
||||
using namespace Windows::ApplicationModel::DataTransfer;
|
||||
using namespace Windows::ApplicationModel::Resources;
|
||||
using namespace Windows::Globalization;
|
||||
using namespace Windows::Storage;
|
||||
|
||||
namespace CalculatorUnitTests
|
||||
{
|
||||
extern void ChangeMode(StandardCalculatorViewModel^ viewModel, int mode);
|
||||
|
||||
#define ASSERT_POSITIVE_TESTCASES(func, dataSet) \
|
||||
{\
|
||||
int size = sizeof(dataSet)/sizeof(*dataSet);\
|
||||
while(--size)\
|
||||
{\
|
||||
VERIFY_ARE_EQUAL(func(dataSet[size]), dataSet[size]);\
|
||||
}\
|
||||
}
|
||||
|
||||
#define ASSERT_NEGATIVE_TESTCASES(func, dataSet) \
|
||||
{\
|
||||
int size = sizeof(dataSet)/sizeof(*dataSet);;\
|
||||
while(--size)\
|
||||
{\
|
||||
VERIFY_ARE_EQUAL(func(dataSet[size]), StringReference(L"NoOp"));\
|
||||
}\
|
||||
}
|
||||
|
||||
// returns a iterator from end
|
||||
#define START_LOOP(dataSet)\
|
||||
{\
|
||||
int size = sizeof(dataSet)/sizeof(*dataSet);\
|
||||
while(--size)\
|
||||
{
|
||||
|
||||
#define END_LOOP\
|
||||
}\
|
||||
}
|
||||
|
||||
class CopyPasteManagerTest
|
||||
{
|
||||
public:
|
||||
TEST_CLASS(CopyPasteManagerTest);
|
||||
|
||||
TEST_METHOD(FunctionalCopyPasteTest);
|
||||
TEST_METHOD(ValidateStandardPasteExpressionTest);
|
||||
TEST_METHOD(ValidateScientificPasteExpressionTest);
|
||||
TEST_METHOD(ValidateProgrammerDecPasteExpressionTest);
|
||||
TEST_METHOD(ValidateProgrammerOctPasteExpressionTest);
|
||||
TEST_METHOD(ValidateProgrammerHexPasteExpressionTest);
|
||||
TEST_METHOD(ValidateProgrammerBinPasteExpressionTest);
|
||||
TEST_METHOD(ValidateConverterPasteExpressionTest);
|
||||
|
||||
TEST_METHOD(ValidatePasteExpressionErrorStates)
|
||||
{
|
||||
wstring exp_TooLong = L"";
|
||||
for (int i = 0; i < m_CopyPasteManager.MaxPasteableLength / 8; i++)
|
||||
{
|
||||
exp_TooLong += L"-1234567";
|
||||
}
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.ValidatePasteExpression(StringReference(exp_TooLong.c_str()), ViewMode::Standard, CategoryGroupType::Calculator, -1, -1), StringReference(exp_TooLong.c_str()), L"Verify ValidatePasteExpression handles expressions up to max length");
|
||||
exp_TooLong += L"1";
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.ValidatePasteExpression(StringReference(exp_TooLong.c_str()), ViewMode::Standard, CategoryGroupType::Calculator, -1, -1), 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, -1), StringReference(L"NoOp"), L"Verify empty string is invalid");
|
||||
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.ValidatePasteExpression(StringReference(L"123e456"), ViewMode::Standard, CategoryGroupType::Calculator, -1, -1), 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, -1), StringReference(L"NoOp"), L"Verify pasting without a ViewMode or Category is invalid");
|
||||
};
|
||||
|
||||
TEST_METHOD(ValidateExtractOperands)
|
||||
{
|
||||
vector<wstring> results = {};
|
||||
|
||||
vector<wstring> 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);
|
||||
|
||||
vector<wstring> 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);
|
||||
|
||||
vector<wstring> 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);
|
||||
|
||||
vector<wstring> twoOperandsParens = { L"((45)", L"(-30))" };
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.ExtractOperands(L"((45)+(-30))", ViewMode::Scientific), twoOperandsParens);
|
||||
};
|
||||
|
||||
TEST_METHOD(ValidateExtractOperandsErrors)
|
||||
{
|
||||
wstring exp_OperandLimit = L"";
|
||||
for (int i = 0; i < m_CopyPasteManager.MaxOperandCount; i++)
|
||||
{
|
||||
exp_OperandLimit += L"+1";
|
||||
}
|
||||
VERIFY_ARE_EQUAL(m_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(), 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");
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.ExtractOperands(L"12e10000", ViewMode::Standard).size(), 0, L"Verify ExtractOperands returns empty vector when the exponent is too long");
|
||||
};
|
||||
|
||||
TEST_METHOD(ValidateExpressionRegExMatch)
|
||||
{
|
||||
VERIFY_IS_FALSE(m_CopyPasteManager.ExpressionRegExMatch(vector<wstring>{}, ViewMode::Standard, CategoryGroupType::Calculator, -1, -1), L"Verify empty list of operands returns false.");
|
||||
VERIFY_IS_FALSE(m_CopyPasteManager.ExpressionRegExMatch(vector<wstring>{ L"123" }, ViewMode::None, CategoryGroupType::Calculator, -1, -1), L"Verify invalid ViewMode/CategoryGroups return false.");
|
||||
VERIFY_IS_FALSE(m_CopyPasteManager.ExpressionRegExMatch(vector<wstring>{ L"123" }, ViewMode::Currency, CategoryGroupType::None, -1, -1), L"Verify invalid ViewMode/CategoryGroups return false.");
|
||||
|
||||
Log::Comment(L"Verify operand lengths > max return false.");
|
||||
VERIFY_IS_FALSE(m_CopyPasteManager.ExpressionRegExMatch(vector<wstring>{ L"12345678901234567" }, ViewMode::Standard, CategoryGroupType::Calculator, -1, -1));
|
||||
VERIFY_IS_FALSE(m_CopyPasteManager.ExpressionRegExMatch(vector<wstring>{ L"123456789012345678901234567890123" }, ViewMode::Scientific, CategoryGroupType::Calculator, -1, -1));
|
||||
VERIFY_IS_FALSE(m_CopyPasteManager.ExpressionRegExMatch(vector<wstring>{ L"12345678901234567" }, ViewMode::None, CategoryGroupType::Converter, -1, -1));
|
||||
VERIFY_IS_FALSE(m_CopyPasteManager.ExpressionRegExMatch(vector<wstring>{ L"11111111111111111" }, ViewMode::Programmer, CategoryGroupType::Calculator, HexBase, QwordType));
|
||||
VERIFY_IS_FALSE(m_CopyPasteManager.ExpressionRegExMatch(vector<wstring>{ L"12345678901234567890" }, ViewMode::Programmer, CategoryGroupType::Calculator, DecBase, QwordType));
|
||||
VERIFY_IS_FALSE(m_CopyPasteManager.ExpressionRegExMatch(vector<wstring>{ L"11111111111111111111111" }, ViewMode::Programmer, CategoryGroupType::Calculator, OctBase, QwordType));
|
||||
VERIFY_IS_FALSE(m_CopyPasteManager.ExpressionRegExMatch(vector<wstring>{ L"10000000000000000000000000000000000000000000000000000000000000000" }, ViewMode::Programmer, CategoryGroupType::Calculator, BinBase, QwordType));
|
||||
|
||||
VERIFY_IS_FALSE(m_CopyPasteManager.ExpressionRegExMatch(vector<wstring>{ L"9223372036854775808" }, ViewMode::Programmer, CategoryGroupType::Calculator, DecBase, QwordType), L"Verify operand values > max return false.");
|
||||
|
||||
VERIFY_IS_TRUE(m_CopyPasteManager.ExpressionRegExMatch(vector<wstring>{ L"((((((((((((((((((((123))))))))))))))))))))" }, ViewMode::Scientific, CategoryGroupType::Calculator, -1, -1), L"Verify sanitized operand is detected as within max length.");
|
||||
VERIFY_IS_TRUE(m_CopyPasteManager.ExpressionRegExMatch(vector<wstring>{ L"9223372036854775807" }, ViewMode::Programmer, CategoryGroupType::Calculator, DecBase, QwordType), L"Verify operand values == max return true.");
|
||||
|
||||
Log::Comment(L"Verify all operands must match patterns.");
|
||||
VERIFY_IS_TRUE(m_CopyPasteManager.ExpressionRegExMatch(vector<wstring>{ L"123", L"456" }, ViewMode::Standard, CategoryGroupType::Calculator, -1, -1));
|
||||
VERIFY_IS_FALSE(m_CopyPasteManager.ExpressionRegExMatch(vector<wstring>{ L"123", L"1e23" }, ViewMode::Standard, CategoryGroupType::Calculator, -1, -1));
|
||||
|
||||
VERIFY_IS_TRUE(m_CopyPasteManager.ExpressionRegExMatch(vector<wstring>{ L"1.23e+456" }, ViewMode::Scientific, CategoryGroupType::Calculator, -1, -1), L"Verify operand only needs to match one pattern.");
|
||||
|
||||
VERIFY_IS_FALSE(m_CopyPasteManager.ExpressionRegExMatch(vector<wstring>{ L"123", L"12345678901234567" }, ViewMode::Standard, CategoryGroupType::Calculator, -1, -1), L"Verify all operands must be within maxlength");
|
||||
VERIFY_IS_FALSE(m_CopyPasteManager.ExpressionRegExMatch(vector<wstring>{ L"123", L"9223372036854775808" }, ViewMode::Programmer, CategoryGroupType::Calculator, DecBase, QwordType), L"Verify all operand must be within max value.");
|
||||
};
|
||||
|
||||
TEST_METHOD(ValidateGetMaxOperandLengthAndValue)
|
||||
{
|
||||
pair<size_t, unsigned long long int> standardModeMaximums = make_pair(m_CopyPasteManager.MaxStandardOperandLength, 0);
|
||||
pair<size_t, unsigned long long int> scientificModeMaximums = make_pair(m_CopyPasteManager.MaxScientificOperandLength, 0);
|
||||
pair<size_t, unsigned long long int> converterModeMaximums = make_pair(m_CopyPasteManager.MaxConverterInputLength, 0);
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Standard, CategoryGroupType::None, -1, -1), standardModeMaximums, L"Verify Standard mode maximum values");
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Scientific, CategoryGroupType::None, -1, -1), scientificModeMaximums, L"Verify Scientific mode maximum values");
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::None, CategoryGroupType::Converter, -1, -1), converterModeMaximums, 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;
|
||||
Log::Comment(L"Verify Programmer Mode HexBase maximum values");
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, HexBase, QwordType), make_pair((size_t)16u, ullQwordMax));
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, HexBase, DwordType), make_pair((size_t)8u, ullDwordMax));
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, HexBase, WordType), make_pair((size_t)4u, ullWordMax));
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, HexBase, ByteType), make_pair((size_t)2u, ullByteMax));
|
||||
|
||||
Log::Comment(L"Verify Programmer Mode DecBase maximum values");
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, DecBase, QwordType), make_pair((size_t)19u, ullQwordMax >> 1));
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, DecBase, DwordType), make_pair((size_t)10u, ullDwordMax >> 1));
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, DecBase, WordType), make_pair((size_t)5u, ullWordMax >> 1));
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, DecBase, ByteType), make_pair((size_t)3u, ullByteMax >> 1));
|
||||
|
||||
Log::Comment(L"Verify Programmer Mode OctBase maximum values");
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, OctBase, QwordType), make_pair((size_t)22u, ullQwordMax));
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, OctBase, DwordType), make_pair((size_t)11u, ullDwordMax));
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, OctBase, WordType), make_pair((size_t)6u, ullWordMax));
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, OctBase, ByteType), make_pair((size_t)3u, ullByteMax));
|
||||
|
||||
Log::Comment(L"Verify Programmer Mode BinBase maximum values");
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, BinBase, QwordType), make_pair((size_t)64u, ullQwordMax));
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, BinBase, DwordType), make_pair((size_t)32u, ullDwordMax));
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, BinBase, WordType), make_pair((size_t)16u, ullWordMax));
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, BinBase, ByteType), make_pair((size_t)8u, ullByteMax));
|
||||
|
||||
Log::Comment(L"Verify invalid ViewModes/Categories return 0 for max values");
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::None, CategoryGroupType::None, -1, -1), make_pair((size_t)0u, 0ull));
|
||||
};
|
||||
|
||||
TEST_METHOD(ValidateSanitizeOperand)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.SanitizeOperand(L"((1234"), L"1234");
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.SanitizeOperand(L"1234))"), L"1234");
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.SanitizeOperand(L"-1234"), L"1234");
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.SanitizeOperand(L"12-34"), L"1234");
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.SanitizeOperand(L"((((1234))))"), L"1234");
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.SanitizeOperand(L"1'2'3'4"), L"1234");
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.SanitizeOperand(L"'''''1234''''"), L"1234");
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.SanitizeOperand(L"1_2_3_4"), L"1234");
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.SanitizeOperand(L"______1234___"), L"1234");
|
||||
};
|
||||
|
||||
TEST_METHOD(ValidateTryOperandToULL)
|
||||
{
|
||||
unsigned long long int result = 0;
|
||||
|
||||
Log::Comment(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);
|
||||
|
||||
Log::Comment(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);
|
||||
|
||||
Log::Comment(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);
|
||||
|
||||
Log::Comment(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);
|
||||
|
||||
Log::Comment(L"Verify TryOperandToULL invalid numberBase defaults to DecBase");
|
||||
VERIFY_IS_TRUE(m_CopyPasteManager.TryOperandToULL(L"1234", 128, result));
|
||||
VERIFY_ARE_EQUAL(result, 1234ull);
|
||||
|
||||
Log::Comment(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));
|
||||
// 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));
|
||||
|
||||
};
|
||||
|
||||
TEST_METHOD(ValidateStandardScientificOperandLength)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.StandardScientificOperandLength(L""), 0);
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.StandardScientificOperandLength(L"0.2"), 1);
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.StandardScientificOperandLength(L"1.2"), 2);
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.StandardScientificOperandLength(L"0."), 0);
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.StandardScientificOperandLength(L"12345"), 5);
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.StandardScientificOperandLength(L"-12345"), 6);
|
||||
|
||||
};
|
||||
|
||||
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"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"", 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"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);
|
||||
};
|
||||
|
||||
private:
|
||||
CopyPasteManager m_CopyPasteManager;
|
||||
String^ ValidateStandardPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Standard, -1/*number base*/, -1/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateScientificPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Scientific, -1/*number base*/, -1/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateConverterPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::None, CategoryGroupType::Converter, -1/*number base*/, -1/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerHexQwordPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, HexBase/*number base*/, QwordType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerHexDwordPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, HexBase/*number base*/, DwordType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerHexWordPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, HexBase/*number base*/, WordType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerHexBytePasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, HexBase/*number base*/, ByteType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerDecQwordPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, DecBase/*number base*/, QwordType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerDecDwordPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, DecBase/*number base*/, DwordType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerDecWordPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, DecBase/*number base*/, WordType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerDecBytePasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, DecBase/*number base*/, ByteType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerOctQwordPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, OctBase/*number base*/, QwordType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerOctDwordPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, OctBase/*number base*/, DwordType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerOctWordPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, OctBase/*number base*/, WordType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerOctBytePasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, OctBase/*number base*/, ByteType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerBinQwordPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, BinBase/*number base*/, QwordType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerBinDwordPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, BinBase/*number base*/, DwordType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerBinWordPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, BinBase/*number base*/, WordType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerBinBytePasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, BinBase/*number base*/, ByteType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
/*************************************
|
||||
standard:
|
||||
can paste simple numbers / expressions not exponential numbers / expressions
|
||||
|
||||
scientific :
|
||||
can paste exponential numbers / expressions too
|
||||
|
||||
programmer :
|
||||
can paste specific numbers / expressions based on radixes.Hex numbers such 13abe is allowed when radix is set to hex, but not allowed otherwise.
|
||||
|
||||
converter :
|
||||
can paste simple numbers not expressions
|
||||
|
||||
List of test cases:
|
||||
1. simple unsigned number
|
||||
2. negative number
|
||||
3. exponential number with positive exp
|
||||
4. exponential number with negative exp
|
||||
5. exponential number with unsigned exp
|
||||
6. exponential number with very large(larger than 4 digit) exp
|
||||
7. expression involving simple numbers
|
||||
8. expression involving exponential numbers
|
||||
9. number with random text like xyz
|
||||
10. hex numbers
|
||||
11. binary numbers
|
||||
12. octal numbers
|
||||
13. very large number
|
||||
14. number with some escape characters in b/w like ",/. \n\r ", '"
|
||||
15. expression involving sin, cos or other mathematic functions
|
||||
16. expression having more than one operator in b/w operands
|
||||
17. expression involving open and close parenthesis (, )
|
||||
|
||||
****************************************/
|
||||
|
||||
void CopyPasteManagerTest::FunctionalCopyPasteTest()
|
||||
{
|
||||
// Doesn't have test where converter is involved. Will add such a test later.
|
||||
StandardCalculatorViewModel^ scvm = ref new StandardCalculatorViewModel();
|
||||
scvm->IsStandard = true;
|
||||
String^ input[] = { 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" };
|
||||
|
||||
START_LOOP(input)
|
||||
// paste number in standard mode and then validate the pastability of displayed number for other modes
|
||||
scvm->OnPaste(input[size], ViewMode::Standard);
|
||||
VERIFY_ARE_EQUAL(ValidateStandardPasteExpression(scvm->DisplayValue), scvm->DisplayValue);
|
||||
VERIFY_ARE_EQUAL(ValidateScientificPasteExpression(scvm->DisplayValue), scvm->DisplayValue);
|
||||
VERIFY_ARE_EQUAL(ValidateProgrammerHexQwordPasteExpression(scvm->DisplayValue), scvm->DisplayValue);
|
||||
END_LOOP
|
||||
}
|
||||
|
||||
|
||||
void CopyPasteManagerTest::ValidateStandardPasteExpressionTest()
|
||||
{
|
||||
String^ positiveInput[] = { L"123", L"+123", L"-133", L"12345.", L"+12.34", L"12.345", L"012.034", L"-23.032", L"-.123", L".1234", L"012.012", L"123+456", L"123+-234", L"123*-345", L"123*4*-3", L"123*+4*-3", L"1,234", L"1 2 3", L"\n\r1,234\n", L"\f\n1+2\t\r\v\x85", L"\n 1+\n2 ", L"1\"2", L"1234567891234567"/*boundary condition <=16 digits*/, L"2+2=", L"2+2= " };
|
||||
String^ negativeInput[] = { L"(123)+(456)", L"1.2e23"/*unsigned exponent*/, L"12345e-23", L"abcdef", L"xyz", L"ABab", L"e+234", L"12345678912345678"/*boundary condition: greater than 16 digits*/, L"SIN(2)", L"2+2==", L"2=+2" };
|
||||
|
||||
ASSERT_POSITIVE_TESTCASES(ValidateStandardPasteExpression, positiveInput);
|
||||
ASSERT_NEGATIVE_TESTCASES(ValidateStandardPasteExpression, negativeInput);
|
||||
}
|
||||
|
||||
void CopyPasteManagerTest::ValidateScientificPasteExpressionTest()
|
||||
{
|
||||
String^ positiveInput[] = { L"123", L"+123", L"-133", L"123+456", L"12345e+023", L"1,234", L"1.23", L"-.123", L".1234", L"012.012", L"123+-234", L"123*-345", L"123*4*-3", L"123*+4*-3", L"1 2 3", L"\n\r1,234\n", L"\f\n1+2\t\r\v\x85", L"\n 1+\n2 ", L"1\"2", L"1.2e+023", L"12345e-23", L"(123)+(456)", L"12345678912345678123456789012345", L"(123)+(456)=", L"2+2= " };
|
||||
String^ negativeInput[] = { L"1.2e23"/*unsigned exponent*/, L"abcdef", L"xyz", L"ABab", L"e+234", L"123456789123456781234567890123456"/*boundary condition: greater than 32 digits*/, L"SIN(2)", L"2+2==", L"2=+2" };
|
||||
|
||||
ASSERT_POSITIVE_TESTCASES(ValidateScientificPasteExpression, positiveInput);
|
||||
ASSERT_NEGATIVE_TESTCASES(ValidateScientificPasteExpression, negativeInput);
|
||||
}
|
||||
|
||||
void CopyPasteManagerTest::ValidateProgrammerHexPasteExpressionTest()
|
||||
{
|
||||
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"12345e-23"/*note: here is considered as E of hex*/, L"\n\r1,234\n", L"\f\n1+2\t\r\v\x85", L"\f\n1+2\t\r\v\x85", L"\n 1+\n2 ", L"e+234", L"1\"2", L"(123)+(456)", L"abcdef", L"ABab", L"ABCDF21abc41a"/*within boundary*/, L"0x1234", L"0xab12", L"0X1234", L"AB12h", L"BC34H", L"1234u", L"1234ul", L"1234ULL", L"2+2=", L"2+2= " };
|
||||
String^ qwordNegativeInput[] = { L"+123", L"1.23"/*floating number*/, L"1''2", L"'123", L"123'", L"1__2", L"_123", L"123_", L"-133", L"1.2e+023", L"1.2e23"/*unsigned exponent*/, L"xyz", L"ABCDEF21abc41abc7"/*outside boundary of 16 digitis*/, L"SIN(2)", L"123+-234", L"1234x", L"A0x1234", L"0xx1234", L"1234uu", L"1234ulll", L"2+2==", L"2=+2" };
|
||||
|
||||
ASSERT_POSITIVE_TESTCASES(ValidateProgrammerHexQwordPasteExpression, qwordPositiveInput);
|
||||
ASSERT_NEGATIVE_TESTCASES(ValidateProgrammerHexQwordPasteExpression, qwordNegativeInput);
|
||||
|
||||
String^ dwordPositiveInput[] = { L"123", L"123+456", L"1,234", L"1 2 3", L"1'2'3'4", L"1_2_3_4", L"12345e-23"/*note: here is considered as E of hex*/, L"\n\r1,234\n", L"\f\n1+2\t\r\v\x85", L"\n 1+\n2 ", L"e+234", L"1\"2", L"(123)+(456)", L"abcdef", L"ABab", L"ABCD123a"/*within boundary*/, L"0x1234", L"0xab12", L"0X1234", L"AB12h", L"BC34H", L"1234u", L"1234ul", L"1234ULL" };
|
||||
String^ dwordNegativeInput[] = { L"+123", L"1.23"/*floating number*/, L"1''2", L"'123", L"123'", L"1__2", L"_123", L"123_", L"-133", L"1.2e+023", L"1.2e23"/*unsigned exponent*/, L"xyz", L"ABCD123ab"/*outside boundary of 8 digitis*/, L"SIN(2)", L"123+-234", L"1234x", L"A0x1234", L"0xx1234", L"1234uu", L"1234ulll" };
|
||||
|
||||
ASSERT_POSITIVE_TESTCASES(ValidateProgrammerHexDwordPasteExpression, dwordPositiveInput);
|
||||
ASSERT_NEGATIVE_TESTCASES(ValidateProgrammerHexDwordPasteExpression, dwordNegativeInput);
|
||||
|
||||
String^ wordPositiveInput[] = { L"123", L"13+456", L"1,34", L"12 3", L"1'2'3'4", L"1_2_3_4", L"15e-23"/*note: here is considered as E of hex*/, L"\r1", L"\n\r1,4", L"\n1,4\n", L"\f\n1+2\t\r\v", L"\n 1+\n2 ", L"e+24", L"1\"2", L"(23)+(4)", L"aef", L"ABab", L"A1a3"/*within boundary*/, L"0x1234", L"0xab12", L"0X1234", L"AB12h", L"BC34H", L"1234u", L"1234ul", L"1234ULL" };
|
||||
String^ wordNegativeInput[] = { L"+123", L"1.23"/*floating number*/, L"1''2", L"'123", L"123'", L"1__2", L"_123", L"123_", L"-133", L"1.2e+023", L"1.2e23"/*unsigned exponent*/, L"xyz", L"A1a3b"/*outside boundary of 4 digitis*/, L"SIN(2)", L"123+-234", L"1234x", L"A0x1234", L"0xx1234", L"1234uu", L"1234ulll" };
|
||||
|
||||
ASSERT_POSITIVE_TESTCASES(ValidateProgrammerHexWordPasteExpression, wordPositiveInput);
|
||||
ASSERT_NEGATIVE_TESTCASES(ValidateProgrammerHexWordPasteExpression, wordNegativeInput);
|
||||
|
||||
String^ bytePositiveInput[] = { L"13", L"13+6", L"1,4", L"2 3", L"1'2", L"1_2", L"5e-3"/*note: here is considered as E of hex*/, L"\r1", L"a", L"ab", L"A1"/*within boundary*/, L"0x12", L"0xab", L"0X12", L"A9h", L"B8H", L"12u", L"12ul", L"12ULL" };
|
||||
String^ byteNegativeInput[] = { L"+3", L"1.2"/*floating number*/, L"1''2", L"'12", L"12'", L"1__2", L"_12", L"12_", L"-3", L"1.1e+02", L"1.2e3"/*unsigned exponent*/, L"xz", L"A3a"/*outside boundary of 2 digitis*/, L"SIN(2)", L"13+-23", L"12x", L"A0x1", L"0xx12", L"12uu", L"12ulll" };
|
||||
|
||||
ASSERT_POSITIVE_TESTCASES(ValidateProgrammerHexBytePasteExpression, bytePositiveInput);
|
||||
ASSERT_NEGATIVE_TESTCASES(ValidateProgrammerHexBytePasteExpression, byteNegativeInput);
|
||||
}
|
||||
|
||||
void CopyPasteManagerTest::ValidateProgrammerDecPasteExpressionTest()
|
||||
{
|
||||
String^ qwordPositiveInput[] = { L"123", L"+123", L"-133", 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"123+-234", L"123*-345", L"123*4*-3", L"123*+4*-3", L"9223372036854775807", L"-9223372036854775807"/*boundary condition: max/min allowed number*/, L"0n1234", L"0N1234", L"1234u", L"1234ul", L"1234ULL", L"2+2=", L"2+2= " };
|
||||
String^ qwordNegativeInput[] = { L"1.23", L"1''2", L"'123", L"123'", L"1__2", L"_123", L"123_", L"1.2e23"/*unsigned exponent*/, L"1.2e+023", L"12345e-23", L"abcdef", L"xyz", L"ABab", L"e+234", L"9223372036854775809"/*boundary condition: greater than max allowed number 9223372036854775807*/, L"SIN(2)", L"-0n123", L"0nn1234", L"1234uu", L"1234ulll", L"2+2==", L"2=+2" };
|
||||
|
||||
ASSERT_POSITIVE_TESTCASES(ValidateProgrammerDecQwordPasteExpression, qwordPositiveInput);
|
||||
ASSERT_NEGATIVE_TESTCASES(ValidateProgrammerDecQwordPasteExpression, qwordNegativeInput);
|
||||
|
||||
String^ dwordPositiveInput[] = { L"123", L"+123", L"-133", 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"123+-234", L"123*-345", L"123*4*-3", L"123*+4*-3", L"2147483647", L"-2147483647"/*boundary condition: max/min allowed number*/, L"0n1234", L"0N1234", L"1234u", L"1234ul", L"1234ULL" };
|
||||
String^ dwordNegativeInput[] = { L"1.23", L"1''2", L"'123", L"123'", L"1__2", L"_123", L"123_", L"1.2e23"/*unsigned exponent*/, L"1.2e+023", L"12345e-23", L"abcdef", L"xyz", L"ABab", L"e+234", L"2147483649"/*boundary condition: greater than max allowed number 2147483647*/, L"SIN(2)", L"-0n123", L"0nn1234", L"1234uu", L"1234ulll" };
|
||||
|
||||
ASSERT_POSITIVE_TESTCASES(ValidateProgrammerDecDwordPasteExpression, dwordPositiveInput);
|
||||
ASSERT_NEGATIVE_TESTCASES(ValidateProgrammerDecDwordPasteExpression, dwordNegativeInput);
|
||||
|
||||
String^ wordPositiveInput[] = { L"123", L"+123", L"-133", L"123+456", L"1,234", L"1 2 3", L"1'2'3'4", L"1_2_3_4", L"\f\n1+2\t\r\v\x85", L"1\"2", L"(123)+(456)", L"123+-234", L"123*-345", L"123*4*-3", L"123*+4*-3", L"32767", L"-32767"/*boundary condition: max/min allowed number*/, L"0n1234", L"0N1234", L"1234u", L"1234ul", L"1234ULL" };
|
||||
String^ wordNegativeInput[] = { L"1.23", L"1''2", L"'123", L"123'", L"1__2", L"_123", L"123_", L"1.2e23"/*unsigned exponent*/, L"1.2e+023", L"12345e-23", L"abcdef", L"xyz", L"ABab", L"e+234", L"32769"/*boundary condition: greater than max allowed number 32769*/, L"SIN(2)", L"-0n123", L"0nn1234", L"1234uu", L"1234ulll" };
|
||||
|
||||
ASSERT_POSITIVE_TESTCASES(ValidateProgrammerDecWordPasteExpression, wordPositiveInput);
|
||||
ASSERT_NEGATIVE_TESTCASES(ValidateProgrammerDecWordPasteExpression, wordNegativeInput);
|
||||
|
||||
String^ bytePositiveInput[] = { L"13", L"+13", L"-13", L"13+46", L"13+-34", L"13*-3", L"3*4*-3", L"3*+4*-3", L"1,3", L"1 3", L"1'2'3", L"1_2_3", L"1\"2", L"127", L"-127"/*boundary condition: max/min allowed number*/, L"0n123", L"0N123", L"123u", L"123ul", L"123ULL" };
|
||||
String^ byteNegativeInput[] = { L"1.23", L"1''2", L"'123", L"123'", L"1__2", L"_123", L"123_", L"1.2e23"/*unsigned exponent*/, L"1.2e+023", L"15e-23", L"abcdef", L"xyz", L"ABab", L"e+24", L"129"/*boundary condition: greater than max allowed number 127*/, L"SIN(2)", L"-0n123", L"0nn1234", L"123uu", L"123ulll" };
|
||||
|
||||
ASSERT_POSITIVE_TESTCASES(ValidateProgrammerDecBytePasteExpression, bytePositiveInput);
|
||||
ASSERT_NEGATIVE_TESTCASES(ValidateProgrammerDecBytePasteExpression, byteNegativeInput);
|
||||
}
|
||||
|
||||
void CopyPasteManagerTest::ValidateProgrammerOctPasteExpressionTest()
|
||||
{
|
||||
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= " };
|
||||
String^ qwordNegativeInput[] = { L"+123", L"1.23", L"1''2", L"'123", L"123'", L"1__2", L"_123", L"123_", L"-133", L"1.2e23"/*unsigned exponent*/, L"1.2e+023", L"12345e-23", L"abcdef", L"xyz", L"ABab", L"e+234", L"12345678901234567890123"/*boundary condition: greater than max allowed digits 22*/, L"SIN(2)", L"123+-234", L"0ot1234", L"1234uu", L"1234ulll", L"2+2==", L"2=+2" };
|
||||
|
||||
ASSERT_POSITIVE_TESTCASES(ValidateProgrammerOctQwordPasteExpression, qwordPositiveInput);
|
||||
ASSERT_NEGATIVE_TESTCASES(ValidateProgrammerOctQwordPasteExpression, qwordNegativeInput);
|
||||
|
||||
String^ dwordPositiveInput[] = { 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"37777777777"/*boundary condition: max allowed number*/, L"0t1234", L"0T1234", L"0o1234", L"0O1234", L"1234u", L"1234ul", L"1234ULL" };
|
||||
String^ dwordNegativeInput[] = { L"+123", L"1.23", L"1''2", L"'123", L"123'", L"1__2", L"_123", L"123_", L"-133", L"1.2e23"/*unsigned exponent*/, L"1.2e+023", L"12345e-23", L"abcdef", L"xyz", L"ABab", L"e+234", L"377777777771"/*boundary condition: greater than max allowed number 37777777777*/, L"SIN(2)", L"123+-234", L"0ot1234", L"1234uu", L"1234ulll" };
|
||||
|
||||
ASSERT_POSITIVE_TESTCASES(ValidateProgrammerOctDwordPasteExpression, dwordPositiveInput);
|
||||
ASSERT_NEGATIVE_TESTCASES(ValidateProgrammerOctDwordPasteExpression, dwordNegativeInput);
|
||||
|
||||
String^ wordPositiveInput[] = { L"123", L"123+456", L"1,234", L"1 2 3", L"1'2'3'4", L"1_2_3_4", L"\f\n1+2\t\r\v\x85", L"1\"2", L"(123)+(456)", L"177777"/*boundary condition: max allowed number*/, L"0t1234", L"0T1234", L"0o1234", L"0O1234", L"1234u", L"1234ul", L"1234ULL" };
|
||||
String^ wordNegativeInput[] = { L"+123", L"1.23", L"1''2", L"'123", L"123'", L"1__2", L"_123", L"123_", L"-133", L"1.2e23"/*unsigned exponent*/, L"1.2e+023", L"12345e-23", L"abcdef", L"xyz", L"ABab", L"e+234", L"1777771"/*boundary condition: greater than max allowed number 177777*/, L"SIN(2)", L"123+-234", L"0ot1234", L"1234uu", L"1234ulll" };
|
||||
|
||||
ASSERT_POSITIVE_TESTCASES(ValidateProgrammerOctWordPasteExpression, wordPositiveInput);
|
||||
ASSERT_NEGATIVE_TESTCASES(ValidateProgrammerOctWordPasteExpression, wordNegativeInput);
|
||||
|
||||
String^ bytePositiveInput[] = { L"13", L"13+46", L"1,3", L"1 3", L"1'2'3", L"1_2_3", L"1\"2", L"377"/*boundary condition: max allowed number*/, L"0t123", L"0T123", L"0o123", L"0O123", L"123u", L"123ul", L"123ULL" };
|
||||
String^ byteNegativeInput[] = { L"+123", L"1.23", L"1''2", L"'123", L"123'", L"1__2", L"_123", L"123_", L"-13", L"1.2e23"/*unsigned exponent*/, L"1.2e+023", L"15e-23", L"abcdef", L"xyz", L"ABab", L"e+24", L"477"/*boundary condition: greater than max allowed number 377*/, L"SIN(2)", L"123+-34", L"0ot123", L"123uu", L"123ulll" };
|
||||
|
||||
ASSERT_POSITIVE_TESTCASES(ValidateProgrammerOctBytePasteExpression, bytePositiveInput);
|
||||
ASSERT_NEGATIVE_TESTCASES(ValidateProgrammerOctBytePasteExpression, byteNegativeInput);
|
||||
}
|
||||
|
||||
void CopyPasteManagerTest::ValidateProgrammerBinPasteExpressionTest()
|
||||
{
|
||||
String^ qwordPositiveInput[] = { 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"\f\n1+11\t\r\v\x85", 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"1010101010101010101010101011110110100100101010101001010101001010"/*boundary condition: max allowed digits 64*/, L"1+10=", L"1+10= " };
|
||||
String^ qwordNegativeInput[] = { L"+10101", L"1.01", L"1''0", L"'101", L"101'", L"1__0", L"_101", L"101_", L"-10101001", L"123", L"1.2e23"/*unsigned exponent*/, L"1.2e+023", L"101010e-1010", L"abcdef", L"xyz", L"ABab", L"e+10101", L"b1001", L"10b01", L"0x10", L"1001x", L"1001h", L"0bb1111", L"1111uu", L"1111ulll", L"10101010101010101010101010111101101001001010101010010101010010100"/*boundary condition: greater than max allowed digits 64*/, L"SIN(01010)", L"10+-10101010101", L"1+10==", L"1=+10" };
|
||||
|
||||
ASSERT_POSITIVE_TESTCASES(ValidateProgrammerBinQwordPasteExpression, qwordPositiveInput);
|
||||
ASSERT_NEGATIVE_TESTCASES(ValidateProgrammerBinQwordPasteExpression, qwordNegativeInput);
|
||||
|
||||
String^ dwordPositiveInput[] = { 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"\f\n1+11\t\r\v\x85", 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"10101001001010101101010111111100"/*boundary condition: max allowed number*/ };
|
||||
String^ dwordNegativeInput[] = { L"+10101", L"1.01", L"1''0", L"'101", L"101'", L"1__0", L"_101", L"101_", L"-10101001", L"123", L"1.2e23"/*unsigned exponent*/, L"1.2e+023", L"101010e-1010", L"abcdef", L"xyz", L"ABab", L"e+10101", L"b1001", L"10b01", L"0x10", L"1001x", L"1001h", L"0bb1111", L"1111uu", L"1111ulll", L"101010010010101011010101111111001"/*boundary condition: greater than max allowed digits 32*/, L"SIN(01010)", L"10+-10101010101" };
|
||||
|
||||
ASSERT_POSITIVE_TESTCASES(ValidateProgrammerBinDwordPasteExpression, dwordPositiveInput);
|
||||
ASSERT_NEGATIVE_TESTCASES(ValidateProgrammerBinDwordPasteExpression, dwordNegativeInput);
|
||||
|
||||
String^ wordPositiveInput[] = { 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"\f\n1+11\t\r\v\x85", 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"1010101010010010"/*boundary condition: max allowed number*/ };
|
||||
String^ wordNegativeInput[] = { L"+10101", L"1.01", L"1''0", L"'101", L"101'", L"1__0", L"_101", L"101_", L"-10101001", L"123", L"1.2e23"/*unsigned exponent*/, L"1.2e+023", L"101010e-1010", L"abcdef", L"xyz", L"ABab", L"e+10101", L"b1001", L"10b01", L"0x10", L"1001x", L"1001h", L"0bb1111", L"1111uu", L"1111ulll", L"10101010100100101"/*boundary condition: greater than max allowed digits 16*/, L"SIN(01010)", L"10+-10101010101" };
|
||||
|
||||
ASSERT_POSITIVE_TESTCASES(ValidateProgrammerBinWordPasteExpression, wordPositiveInput);
|
||||
ASSERT_NEGATIVE_TESTCASES(ValidateProgrammerBinWordPasteExpression, wordNegativeInput);
|
||||
|
||||
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*/ };
|
||||
String^ byteNegativeInput[] = { L"+10101", L"1.01", L"1''0", L"'101", L"101'", L"1__0", L"_101", L"101_", L"-10101001", L"123", L"1.2e23"/*unsigned exponent*/, L"1.2e+023", L"101010e-1010", L"abcdef", L"xyz", L"ABab", L"e+10101", L"b1001", L"10b01", L"0x10", L"1001x", L"1001h", L"0bb1111", L"1111uu", L"1111ulll", L"101000101"/*boundary condition: greater than max allowed digits 8*/, L"SIN(01010)", L"10+-1010101" };
|
||||
|
||||
ASSERT_POSITIVE_TESTCASES(ValidateProgrammerBinBytePasteExpression, bytePositiveInput);
|
||||
ASSERT_NEGATIVE_TESTCASES(ValidateProgrammerBinBytePasteExpression, byteNegativeInput);
|
||||
}
|
||||
|
||||
void CopyPasteManagerTest::ValidateConverterPasteExpressionTest()
|
||||
{
|
||||
String^ positiveInput[] = { L"123", L"+123", L"-133", L"12345.", L"012.012", L"1,234", L"1 2 3", L"\n\r1,234\n", L"\f\n12\t\r\v\x85", L"1\"2", L"100=", L"100= " };
|
||||
String^ negativeInput[] = { L"(123)+(456)", L"1.2e23"/*unsigned exponent*/, L"12345e-23", L"\n 1+\n2 ", L"123+456", L"abcdef", L"\n 1+\n2 ", L"xyz", L"ABab", L"e+234", L"12345678912345678"/*boundary condition: greater than 16 bits*/, L"SIN(2)", L"123+-234", L"100==", L"=100" };
|
||||
|
||||
ASSERT_POSITIVE_TESTCASES(ValidateConverterPasteExpression, positiveInput);
|
||||
ASSERT_NEGATIVE_TESTCASES(ValidateConverterPasteExpression, negativeInput);
|
||||
}
|
||||
}
|
||||
|
605
internal/CalculatorUnitTests/CurrencyConverterUnitTests.cpp
Normal file
@@ -0,0 +1,605 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include <WexTestClass.h>
|
||||
|
||||
#include "CalcViewModel\DataLoaders\CurrencyDataLoader.h"
|
||||
#include "CalcViewModel\Common\LocalizationService.h"
|
||||
|
||||
using namespace CalculatorApp::Common;
|
||||
using namespace CalculatorApp::Common::LocalizationServiceProperties;
|
||||
using namespace CalculatorApp::DataLoaders;
|
||||
using namespace CalculatorApp::ViewModel;
|
||||
using namespace CalculatorUnitTests;
|
||||
using namespace Concurrency;
|
||||
using namespace Platform;
|
||||
using namespace std;
|
||||
using namespace UnitConversionManager;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Storage;
|
||||
using namespace Windows::Web::Http;
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace DataLoaders
|
||||
{
|
||||
class MockCurrencyHttpClientWithResult : public CurrencyHttpClient
|
||||
{
|
||||
public:
|
||||
MockCurrencyHttpClientWithResult(String^ staticResponse, String^ allRatiosResponse) :
|
||||
m_staticResponse(staticResponse),
|
||||
m_allRatiosResponse(allRatiosResponse)
|
||||
{
|
||||
}
|
||||
|
||||
IAsyncOperationWithProgress<String^, HttpProgress>^ GetCurrencyMetadata() override
|
||||
{
|
||||
return ref new MockAsyncOperationWithProgress(m_staticResponse);
|
||||
}
|
||||
|
||||
IAsyncOperationWithProgress<String^, HttpProgress>^ GetCurrencyRatios() override
|
||||
{
|
||||
return ref new MockAsyncOperationWithProgress(m_allRatiosResponse);
|
||||
}
|
||||
|
||||
private:
|
||||
String^ m_staticResponse;
|
||||
String^ m_allRatiosResponse;
|
||||
};
|
||||
|
||||
class MockCurrencyHttpClientThrowsException : public CurrencyHttpClient
|
||||
{
|
||||
public:
|
||||
MockCurrencyHttpClientThrowsException() {}
|
||||
|
||||
IAsyncOperationWithProgress<String^, HttpProgress>^ GetCurrencyMetadata() override
|
||||
{
|
||||
throw ref new NotImplementedException();
|
||||
}
|
||||
|
||||
IAsyncOperationWithProgress<String^, HttpProgress>^ GetCurrencyRatios() override
|
||||
{
|
||||
throw ref new NotImplementedException();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class DataLoadedCallback : public UnitConversionManager::IViewModelCurrencyCallback
|
||||
{
|
||||
public:
|
||||
DataLoadedCallback(task_completion_event<void> tce) :
|
||||
m_task_completion_event{ tce }
|
||||
{}
|
||||
|
||||
void CurrencyDataLoadFinished(bool didLoad) override
|
||||
{
|
||||
m_task_completion_event.set();
|
||||
}
|
||||
|
||||
void CurrencySymbolsCallback(_In_ const wstring& fromSymbol, _In_ const wstring& toSymbol) override {}
|
||||
void CurrencyRatiosCallback(_In_ const wstring& ratioEquality, _In_ const wstring& accRatioEquality) override {}
|
||||
void CurrencyTimestampCallback(_In_ const std::wstring& timestamp, bool isWeekOldData) override {}
|
||||
void NetworkBehaviorChanged(_In_ int newBehavior) override {}
|
||||
|
||||
private:
|
||||
Concurrency::task_completion_event<void> m_task_completion_event;
|
||||
};
|
||||
|
||||
namespace CalculatorUnitTests
|
||||
{
|
||||
constexpr auto sc_Language_EN = L"en-US";
|
||||
|
||||
const UCM::Category CURRENCY_CATEGORY = { NavCategory::Serialize(ViewMode::Currency), L"Currency", false /*supportsNegative*/ };
|
||||
|
||||
unique_ptr<CurrencyDataLoader> MakeLoaderWithResults(String^ staticResponse, String^ allRatiosResponse)
|
||||
{
|
||||
auto client = make_unique<MockCurrencyHttpClientWithResult>(staticResponse, allRatiosResponse);
|
||||
client->SetSourceCurrencyCode(StringReference(DefaultCurrencyCode.data()));
|
||||
return make_unique<CurrencyDataLoader>(move(client));
|
||||
}
|
||||
|
||||
String^ SerializeContent(const vector<String^>& data)
|
||||
{
|
||||
String^ result = L"";
|
||||
String^ delimiter = CurrencyDataLoaderConstants::CacheDelimiter;
|
||||
for (String^ content : data)
|
||||
{
|
||||
result += (delimiter + content);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool WriteToFileInLocalCacheFolder(String^ filename, String^ content)
|
||||
{
|
||||
try
|
||||
{
|
||||
StorageFolder^ localFolder = ApplicationData::Current->LocalCacheFolder;
|
||||
StorageFile^ file = create_task(localFolder->CreateFileAsync(filename, CreationCollisionOption::ReplaceExisting)).get();
|
||||
create_task(FileIO::WriteTextAsync(file, content)).wait();
|
||||
return true;
|
||||
}
|
||||
catch (Exception^ ex)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool DeleteFileFromLocalCacheFolder(String^ filename)
|
||||
{
|
||||
try
|
||||
{
|
||||
StorageFolder^ folder = ApplicationData::Current->LocalCacheFolder;
|
||||
IAsyncOperation<StorageFile^>^ fileOperation = folder->GetFileAsync(filename);
|
||||
StorageFile^ file = create_task(fileOperation).get();
|
||||
create_task(file->DeleteAsync()).get();
|
||||
return true;
|
||||
}
|
||||
catch (Platform::Exception^ ex)
|
||||
{
|
||||
// FileNotFoundException is a valid result
|
||||
return ex->HResult == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool DeleteCurrencyCacheFiles()
|
||||
{
|
||||
try
|
||||
{
|
||||
bool deletedStaticData = DeleteFileFromLocalCacheFolder(CurrencyDataLoaderConstants::StaticDataFilename);
|
||||
bool deletedAllRatiosData = DeleteFileFromLocalCacheFolder(CurrencyDataLoaderConstants::AllRatiosDataFilename);
|
||||
|
||||
return deletedStaticData && deletedAllRatiosData;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void InsertToLocalSettings(String^ key, Object^ value)
|
||||
{
|
||||
ApplicationData::Current->LocalSettings->Values->Insert(key, value);
|
||||
}
|
||||
|
||||
void RemoveFromLocalSettings(String^ key)
|
||||
{
|
||||
// Safe to call, even if the key does not exist.
|
||||
ApplicationData::Current->LocalSettings->Values->Remove(key);
|
||||
}
|
||||
|
||||
void StandardCacheSetup()
|
||||
{
|
||||
// Insert current time so data is less than a day old.
|
||||
DateTime now = Utils::GetUniversalSystemTime();
|
||||
InsertToLocalSettings(CurrencyDataLoaderConstants::CacheTimestampKey, now);
|
||||
InsertToLocalSettings(CurrencyDataLoaderConstants::CacheLangcodeKey, StringReference(sc_Language_EN));
|
||||
|
||||
VERIFY_IS_TRUE(DeleteCurrencyCacheFiles());
|
||||
|
||||
VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::StaticDataFilename, CurrencyHttpClient::GetRawStaticDataResponse()));
|
||||
VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::AllRatiosDataFilename, CurrencyHttpClient::GetRawAllRatiosDataResponse()));
|
||||
}
|
||||
|
||||
class CurrencyConverterLoadTests
|
||||
{
|
||||
public:
|
||||
TEST_CLASS(CurrencyConverterLoadTests);
|
||||
|
||||
|
||||
TEST_METHOD_SETUP(DeleteCacheFiles)
|
||||
{
|
||||
return DeleteCurrencyCacheFiles();
|
||||
}
|
||||
|
||||
TEST_METHOD(LoadFromCache_Fail_NoCacheKey)
|
||||
{
|
||||
RemoveFromLocalSettings(CurrencyDataLoaderConstants::CacheTimestampKey);
|
||||
|
||||
CurrencyDataLoader loader{ nullptr };
|
||||
|
||||
bool didLoad = loader.TryLoadDataFromCacheAsync().get();
|
||||
|
||||
VERIFY_IS_FALSE(didLoad);
|
||||
VERIFY_IS_FALSE(loader.LoadFinished());
|
||||
VERIFY_IS_FALSE(loader.LoadedFromCache());
|
||||
}
|
||||
|
||||
TEST_METHOD(LoadFromCache_Fail_OlderThanADay)
|
||||
{
|
||||
// Insert 24 hours ago so data is considered stale.
|
||||
// This will cause the load from cache to fail.
|
||||
DateTime now = Utils::GetUniversalSystemTime();
|
||||
DateTime dayOld;
|
||||
dayOld.UniversalTime = now.UniversalTime - CurrencyDataLoaderConstants::DayDuration - 1;
|
||||
InsertToLocalSettings(CurrencyDataLoaderConstants::CacheTimestampKey, dayOld);
|
||||
|
||||
CurrencyDataLoader loader{ nullptr };
|
||||
|
||||
bool didLoad = loader.TryLoadDataFromCacheAsync().get();
|
||||
|
||||
VERIFY_IS_FALSE(didLoad);
|
||||
VERIFY_IS_FALSE(loader.LoadFinished());
|
||||
VERIFY_IS_FALSE(loader.LoadedFromCache());
|
||||
}
|
||||
|
||||
TEST_METHOD(LoadFromCache_Fail_StaticDataFileDoesNotExist)
|
||||
{
|
||||
// Insert current time so data is less than a day old.
|
||||
// This will cause the load to continue to attempt to load the file.
|
||||
DateTime now = Utils::GetUniversalSystemTime();
|
||||
InsertToLocalSettings(CurrencyDataLoaderConstants::CacheTimestampKey, now);
|
||||
|
||||
VERIFY_IS_TRUE(DeleteFileFromLocalCacheFolder(CurrencyDataLoaderConstants::StaticDataFilename));
|
||||
VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::AllRatiosDataFilename, CurrencyHttpClient::GetRawAllRatiosDataResponse()));
|
||||
|
||||
CurrencyDataLoader loader{ nullptr };
|
||||
|
||||
bool didLoad = loader.TryLoadDataFromCacheAsync().get();
|
||||
|
||||
VERIFY_IS_FALSE(didLoad);
|
||||
VERIFY_IS_FALSE(loader.LoadFinished());
|
||||
VERIFY_IS_FALSE(loader.LoadedFromCache());
|
||||
}
|
||||
|
||||
TEST_METHOD(LoadFromCache_Fail_AllRatiosDataFileDoesNotExist)
|
||||
{
|
||||
// Insert current time so data is less than a day old.
|
||||
// This will cause the load to continue to attempt to load the file.
|
||||
DateTime now = Utils::GetUniversalSystemTime();
|
||||
InsertToLocalSettings(CurrencyDataLoaderConstants::CacheTimestampKey, now);
|
||||
|
||||
VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::StaticDataFilename, CurrencyHttpClient::GetRawStaticDataResponse()));
|
||||
VERIFY_IS_TRUE(DeleteFileFromLocalCacheFolder(CurrencyDataLoaderConstants::AllRatiosDataFilename));
|
||||
|
||||
CurrencyDataLoader loader{ nullptr };
|
||||
|
||||
bool didLoad = loader.TryLoadDataFromCacheAsync().get();
|
||||
|
||||
VERIFY_IS_FALSE(didLoad);
|
||||
VERIFY_IS_FALSE(loader.LoadFinished());
|
||||
VERIFY_IS_FALSE(loader.LoadedFromCache());
|
||||
}
|
||||
|
||||
TEST_METHOD(LoadFromCache_Fail_ResponseLanguageChanged)
|
||||
{
|
||||
DateTime now = Utils::GetUniversalSystemTime();
|
||||
InsertToLocalSettings(CurrencyDataLoaderConstants::CacheTimestampKey, now);
|
||||
|
||||
// Tests always use en-US as response language. Insert a different lang-code to fail the test.
|
||||
InsertToLocalSettings(CurrencyDataLoaderConstants::CacheLangcodeKey, L"ar-SA");
|
||||
|
||||
VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::StaticDataFilename, CurrencyHttpClient::GetRawStaticDataResponse()));
|
||||
VERIFY_IS_TRUE(DeleteFileFromLocalCacheFolder(CurrencyDataLoaderConstants::AllRatiosDataFilename));
|
||||
|
||||
CurrencyDataLoader loader{ nullptr };
|
||||
|
||||
bool didLoad = loader.TryLoadDataFromCacheAsync().get();
|
||||
|
||||
VERIFY_IS_FALSE(didLoad);
|
||||
VERIFY_IS_FALSE(loader.LoadFinished());
|
||||
VERIFY_IS_FALSE(loader.LoadedFromCache());
|
||||
}
|
||||
|
||||
TEST_METHOD(LoadFromCache_Success)
|
||||
{
|
||||
StandardCacheSetup();
|
||||
|
||||
CurrencyDataLoader loader{ nullptr };
|
||||
|
||||
bool didLoad = loader.TryLoadDataFromCacheAsync().get();
|
||||
|
||||
VERIFY_IS_TRUE(didLoad);
|
||||
VERIFY_IS_TRUE(loader.LoadFinished());
|
||||
VERIFY_IS_TRUE(loader.LoadedFromCache());
|
||||
}
|
||||
|
||||
TEST_METHOD(LoadFromWeb_Fail_ClientIsNullptr)
|
||||
{
|
||||
CurrencyDataLoader loader{ nullptr };
|
||||
|
||||
bool didLoad = loader.TryLoadDataFromWebAsync().get();
|
||||
|
||||
VERIFY_IS_FALSE(didLoad);
|
||||
VERIFY_IS_FALSE(loader.LoadFinished());
|
||||
VERIFY_IS_FALSE(loader.LoadedFromWeb());
|
||||
}
|
||||
|
||||
TEST_METHOD(LoadFromWeb_Fail_WebException)
|
||||
{
|
||||
CurrencyDataLoader loader{ make_unique<MockCurrencyHttpClientThrowsException>() };
|
||||
|
||||
bool didLoad = loader.TryLoadDataFromWebAsync().get();
|
||||
|
||||
VERIFY_IS_FALSE(didLoad);
|
||||
VERIFY_IS_FALSE(loader.LoadFinished());
|
||||
VERIFY_IS_FALSE(loader.LoadedFromWeb());
|
||||
}
|
||||
|
||||
TEST_METHOD(LoadFromWeb_Success)
|
||||
{
|
||||
String^ staticResponse = CurrencyHttpClient::GetRawStaticDataResponse();
|
||||
String^ allRatiosResponse = CurrencyHttpClient::GetRawAllRatiosDataResponse();
|
||||
unique_ptr<CurrencyDataLoader> loader = MakeLoaderWithResults(staticResponse, allRatiosResponse);
|
||||
|
||||
bool didLoad = loader->TryLoadDataFromWebAsync().get();
|
||||
|
||||
VERIFY_IS_TRUE(didLoad);
|
||||
VERIFY_IS_TRUE(loader->LoadFinished());
|
||||
VERIFY_IS_TRUE(loader->LoadedFromWeb());
|
||||
}
|
||||
|
||||
TEST_METHOD(Load_Success_LoadedFromCache)
|
||||
{
|
||||
StandardCacheSetup();
|
||||
|
||||
CurrencyDataLoader loader{ nullptr };
|
||||
|
||||
auto data_loaded_event = task_completion_event<void>();
|
||||
loader.SetViewModelCallback(make_shared<DataLoadedCallback>(data_loaded_event));
|
||||
|
||||
auto data_loaded_task = create_task(data_loaded_event);
|
||||
loader.LoadData();
|
||||
data_loaded_task.wait();
|
||||
|
||||
VERIFY_IS_TRUE(loader.LoadFinished());
|
||||
VERIFY_IS_TRUE(loader.LoadedFromCache());
|
||||
VERIFY_IS_FALSE(loader.LoadedFromWeb());
|
||||
}
|
||||
|
||||
TEST_METHOD(Load_Success_LoadedFromWeb)
|
||||
{
|
||||
// Insert 24 hours ago so data is considered stale.
|
||||
// This will cause the load from cache to fail.
|
||||
DateTime now = Utils::GetUniversalSystemTime();
|
||||
DateTime dayOld;
|
||||
dayOld.UniversalTime = now.UniversalTime - CurrencyDataLoaderConstants::DayDuration - 1;
|
||||
InsertToLocalSettings(CurrencyDataLoaderConstants::CacheTimestampKey, dayOld);
|
||||
|
||||
String^ staticResponse = CurrencyHttpClient::GetRawStaticDataResponse();
|
||||
String^ allRatiosResponse = CurrencyHttpClient::GetRawAllRatiosDataResponse();
|
||||
unique_ptr<CurrencyDataLoader> loader = MakeLoaderWithResults(staticResponse, allRatiosResponse);
|
||||
|
||||
auto data_loaded_event = task_completion_event<void>();
|
||||
loader->SetViewModelCallback(make_shared<DataLoadedCallback>(data_loaded_event));
|
||||
|
||||
auto data_loaded_task = create_task(data_loaded_event);
|
||||
loader->LoadData();
|
||||
data_loaded_task.wait();
|
||||
|
||||
VERIFY_IS_TRUE(loader->LoadFinished());
|
||||
VERIFY_IS_FALSE(loader->LoadedFromCache());
|
||||
VERIFY_IS_TRUE(loader->LoadedFromWeb());
|
||||
}
|
||||
};
|
||||
|
||||
class CurrencyConverterUnitTests
|
||||
{
|
||||
TEST_CLASS(CurrencyConverterUnitTests);
|
||||
|
||||
const UCM::Unit GetUnit(const vector<UCM::Unit>& unitList, const wstring& target)
|
||||
{
|
||||
return *find_if(begin(unitList), end(unitList), [&target](const UCM::Unit& u) { return u.abbreviation == target; });
|
||||
}
|
||||
|
||||
TEST_METHOD(Loaded_LoadOrderedUnits)
|
||||
{
|
||||
StandardCacheSetup();
|
||||
|
||||
CurrencyDataLoader loader{ nullptr };
|
||||
|
||||
auto data_loaded_event = task_completion_event<void>();
|
||||
loader.SetViewModelCallback(make_shared<DataLoadedCallback>(data_loaded_event));
|
||||
|
||||
auto data_loaded_task = create_task(data_loaded_event);
|
||||
loader.LoadData();
|
||||
data_loaded_task.wait();
|
||||
|
||||
VERIFY_IS_TRUE(loader.LoadFinished());
|
||||
VERIFY_IS_TRUE(loader.LoadedFromCache());
|
||||
VERIFY_IS_FALSE(loader.LoadedFromWeb());
|
||||
|
||||
vector<UCM::Unit> unitList = loader.LoadOrderedUnits(CURRENCY_CATEGORY);
|
||||
VERIFY_ARE_EQUAL(size_t{ 2 }, unitList.size());
|
||||
|
||||
const UCM::Unit usdUnit = GetUnit(unitList, L"USD");
|
||||
const UCM::Unit eurUnit = GetUnit(unitList, L"EUR");
|
||||
|
||||
VERIFY_ARE_EQUAL(StringReference(L"United States - Dollar"), ref new String(usdUnit.name.c_str()));
|
||||
VERIFY_ARE_EQUAL(StringReference(L"USD"), ref new String(usdUnit.abbreviation.c_str()));
|
||||
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Europe - Euro"), ref new String(eurUnit.name.c_str()));
|
||||
VERIFY_ARE_EQUAL(StringReference(L"EUR"), ref new String(eurUnit.abbreviation.c_str()));
|
||||
}
|
||||
|
||||
TEST_METHOD(Loaded_LoadOrderedRatios)
|
||||
{
|
||||
StandardCacheSetup();
|
||||
|
||||
CurrencyDataLoader loader{ nullptr };
|
||||
|
||||
auto data_loaded_event = task_completion_event<void>();
|
||||
loader.SetViewModelCallback(make_shared<DataLoadedCallback>(data_loaded_event));
|
||||
|
||||
auto data_loaded_task = create_task(data_loaded_event);
|
||||
loader.LoadData();
|
||||
data_loaded_task.wait();
|
||||
|
||||
VERIFY_IS_TRUE(loader.LoadFinished());
|
||||
VERIFY_IS_TRUE(loader.LoadedFromCache());
|
||||
VERIFY_IS_FALSE(loader.LoadedFromWeb());
|
||||
|
||||
vector<UCM::Unit> unitList = loader.LoadOrderedUnits(CURRENCY_CATEGORY);
|
||||
VERIFY_ARE_EQUAL(size_t{ 2 }, unitList.size());
|
||||
|
||||
const UCM::Unit usdUnit = GetUnit(unitList, L"USD");
|
||||
const UCM::Unit eurUnit = GetUnit(unitList, L"EUR");
|
||||
|
||||
unordered_map<UCM::Unit, UCM::ConversionData, UCM::UnitHash> ratios = loader.LoadOrderedRatios(usdUnit);
|
||||
VERIFY_ARE_EQUAL(size_t{ 2 }, ratios.size());
|
||||
|
||||
UCM::ConversionData usdRatioData = ratios[usdUnit];
|
||||
VERIFY_IS_TRUE((std::abs(1.0 - usdRatioData.ratio) < 1e-1));
|
||||
|
||||
UCM::ConversionData eurRatioData = ratios[eurUnit];
|
||||
VERIFY_IS_TRUE((std::abs(0.920503 - eurRatioData.ratio) < 1e-6));
|
||||
}
|
||||
|
||||
TEST_METHOD(Loaded_GetCurrencySymbols_Valid)
|
||||
{
|
||||
StandardCacheSetup();
|
||||
|
||||
CurrencyDataLoader loader{ nullptr };
|
||||
|
||||
auto data_loaded_event = task_completion_event<void>();
|
||||
loader.SetViewModelCallback(make_shared<DataLoadedCallback>(data_loaded_event));
|
||||
|
||||
auto data_loaded_task = create_task(data_loaded_event);
|
||||
loader.LoadData();
|
||||
data_loaded_task.wait();
|
||||
|
||||
VERIFY_IS_TRUE(loader.LoadFinished());
|
||||
VERIFY_IS_TRUE(loader.LoadedFromCache());
|
||||
VERIFY_IS_FALSE(loader.LoadedFromWeb());
|
||||
|
||||
vector<UCM::Unit> unitList = loader.LoadOrderedUnits(CURRENCY_CATEGORY);
|
||||
VERIFY_ARE_EQUAL(size_t{ 2 }, unitList.size());
|
||||
|
||||
const UCM::Unit usdUnit = GetUnit(unitList, L"USD");
|
||||
const UCM::Unit eurUnit = GetUnit(unitList, L"EUR");
|
||||
|
||||
const pair<wstring, wstring> symbols = loader.GetCurrencySymbols(usdUnit, eurUnit);
|
||||
|
||||
VERIFY_ARE_EQUAL(ref new String(L"$"), StringReference(symbols.first.c_str()));
|
||||
VERIFY_ARE_EQUAL(ref new String(L"€"), StringReference(symbols.second.c_str()));
|
||||
}
|
||||
|
||||
TEST_METHOD(Loaded_GetCurrencySymbols_Invalid)
|
||||
{
|
||||
StandardCacheSetup();
|
||||
|
||||
CurrencyDataLoader loader{ nullptr };
|
||||
|
||||
auto data_loaded_event = task_completion_event<void>();
|
||||
loader.SetViewModelCallback(make_shared<DataLoadedCallback>(data_loaded_event));
|
||||
|
||||
auto data_loaded_task = create_task(data_loaded_event);
|
||||
loader.LoadData();
|
||||
data_loaded_task.wait();
|
||||
|
||||
VERIFY_IS_TRUE(loader.LoadFinished());
|
||||
VERIFY_IS_TRUE(loader.LoadedFromCache());
|
||||
VERIFY_IS_FALSE(loader.LoadedFromWeb());
|
||||
|
||||
const UCM::Unit fakeUnit1 = {
|
||||
1, L"fakeUnit1", L"FUD1", false, false, false
|
||||
};
|
||||
|
||||
const UCM::Unit fakeUnit2 = {
|
||||
2, L"fakeUnit2", L"FUD2", false, false, false
|
||||
};
|
||||
|
||||
pair<wstring, wstring> symbols = loader.GetCurrencySymbols(fakeUnit1, fakeUnit2);
|
||||
|
||||
VERIFY_ARE_EQUAL(ref new String(L""), StringReference(symbols.first.c_str()));
|
||||
VERIFY_ARE_EQUAL(ref new String(L""), StringReference(symbols.second.c_str()));
|
||||
|
||||
// Verify that when only one unit is valid, both symbols return as empty string.
|
||||
vector<UCM::Unit> unitList = loader.LoadOrderedUnits(CURRENCY_CATEGORY);
|
||||
VERIFY_ARE_EQUAL(size_t{ 2 }, unitList.size());
|
||||
|
||||
const UCM::Unit usdUnit = GetUnit(unitList, L"USD");
|
||||
|
||||
symbols = loader.GetCurrencySymbols(fakeUnit1, usdUnit);
|
||||
|
||||
VERIFY_ARE_EQUAL(ref new String(L""), StringReference(symbols.first.c_str()));
|
||||
VERIFY_ARE_EQUAL(ref new String(L""), StringReference(symbols.second.c_str()));
|
||||
|
||||
symbols = loader.GetCurrencySymbols(usdUnit, fakeUnit1);
|
||||
|
||||
VERIFY_ARE_EQUAL(ref new String(L""), StringReference(symbols.first.c_str()));
|
||||
VERIFY_ARE_EQUAL(ref new String(L""), StringReference(symbols.second.c_str()));
|
||||
}
|
||||
|
||||
TEST_METHOD(Loaded_GetCurrencyRatioEquality_Valid)
|
||||
{
|
||||
StandardCacheSetup();
|
||||
|
||||
CurrencyDataLoader loader{ nullptr };
|
||||
|
||||
auto data_loaded_event = task_completion_event<void>();
|
||||
loader.SetViewModelCallback(make_shared<DataLoadedCallback>(data_loaded_event));
|
||||
|
||||
auto data_loaded_task = create_task(data_loaded_event);
|
||||
loader.LoadData();
|
||||
data_loaded_task.wait();
|
||||
|
||||
VERIFY_IS_TRUE(loader.LoadFinished());
|
||||
VERIFY_IS_TRUE(loader.LoadedFromCache());
|
||||
VERIFY_IS_FALSE(loader.LoadedFromWeb());
|
||||
|
||||
vector<UCM::Unit> unitList = loader.LoadOrderedUnits(CURRENCY_CATEGORY);
|
||||
VERIFY_ARE_EQUAL(size_t{ 2 }, unitList.size());
|
||||
|
||||
const UCM::Unit usdUnit = GetUnit(unitList, L"USD");
|
||||
const UCM::Unit eurUnit = GetUnit(unitList, L"EUR");
|
||||
|
||||
const pair<wstring, wstring> ratio = loader.GetCurrencyRatioEquality(usdUnit, eurUnit);
|
||||
|
||||
VERIFY_ARE_EQUAL(ref new String(L"1 USD = 0.9205 EUR"), StringReference(ratio.first.c_str()));
|
||||
VERIFY_ARE_EQUAL(ref new String(L"1 United States Dollar = 0.9205 Europe Euro"), StringReference(ratio.second.c_str()));
|
||||
}
|
||||
|
||||
TEST_METHOD(Loaded_GetCurrencyRatioEquality_Invalid)
|
||||
{
|
||||
StandardCacheSetup();
|
||||
|
||||
CurrencyDataLoader loader{ nullptr };
|
||||
|
||||
auto data_loaded_event = task_completion_event<void>();
|
||||
loader.SetViewModelCallback(make_shared<DataLoadedCallback>(data_loaded_event));
|
||||
|
||||
auto data_loaded_task = create_task(data_loaded_event);
|
||||
loader.LoadData();
|
||||
data_loaded_task.wait();
|
||||
|
||||
VERIFY_IS_TRUE(loader.LoadFinished());
|
||||
VERIFY_IS_TRUE(loader.LoadedFromCache());
|
||||
VERIFY_IS_FALSE(loader.LoadedFromWeb());
|
||||
|
||||
const UCM::Unit fakeUnit1 = {
|
||||
1, L"fakeUnit1", L"fakeCountry1", L"FUD1", false, false, false
|
||||
};
|
||||
const UCM::Unit fakeUnit2 = {
|
||||
2, L"fakeUnit2", L"fakeCountry2", L"FUD2", false, false, false
|
||||
};
|
||||
|
||||
pair<wstring, wstring> ratio = loader.GetCurrencyRatioEquality(fakeUnit1, fakeUnit2);
|
||||
|
||||
VERIFY_ARE_EQUAL(ref new String(L""), StringReference(ratio.first.c_str()));
|
||||
VERIFY_ARE_EQUAL(ref new String(L""), StringReference(ratio.second.c_str()));
|
||||
|
||||
// Verify that when only one unit is valid, both symbols return as empty string.
|
||||
vector<UCM::Unit> unitList = loader.LoadOrderedUnits(CURRENCY_CATEGORY);
|
||||
VERIFY_ARE_EQUAL(size_t{ 2 }, unitList.size());
|
||||
|
||||
const UCM::Unit usdUnit = GetUnit(unitList, L"USD");
|
||||
|
||||
ratio = loader.GetCurrencyRatioEquality(fakeUnit1, usdUnit);
|
||||
|
||||
VERIFY_ARE_EQUAL(ref new String(L""), StringReference(ratio.first.c_str()));
|
||||
VERIFY_ARE_EQUAL(ref new String(L""), StringReference(ratio.second.c_str()));
|
||||
|
||||
ratio = loader.GetCurrencyRatioEquality(usdUnit, fakeUnit1);
|
||||
|
||||
VERIFY_ARE_EQUAL(ref new String(L""), StringReference(ratio.first.c_str()));
|
||||
VERIFY_ARE_EQUAL(ref new String(L""), StringReference(ratio.second.c_str()));
|
||||
}
|
||||
};
|
||||
}
|
582
internal/CalculatorUnitTests/DateCalculatorUnitTests.cpp
Normal file
@@ -0,0 +1,582 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include <WexTestClass.h>
|
||||
#include "DateUtils.h"
|
||||
|
||||
#include "CalcViewModel\Common\DateCalculator.h"
|
||||
#include "CalcViewModel\DateCalculatorViewModel.h"
|
||||
|
||||
using namespace Platform;
|
||||
using namespace std;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Globalization;
|
||||
using namespace Windows::Globalization::DateTimeFormatting;
|
||||
using namespace CalculatorApp::Common::DateCalculation;
|
||||
using namespace CalculatorApp::ViewModel;
|
||||
|
||||
namespace DateCalculationUnitTests
|
||||
{
|
||||
const int c_numDate = 15;
|
||||
const int c_diffTestCase = 9;
|
||||
const int c_numAddOobDate = 2;
|
||||
const int c_numSubtractOobDate = 2;
|
||||
const int c_addCases = 3;
|
||||
const int c_subtractCases = 3;
|
||||
const int c_dateDiff = 14;
|
||||
|
||||
DateCalculationEngine m_DateCalcEngine(CalendarIdentifiers::Gregorian);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SYSTEMTIME startDate;
|
||||
SYSTEMTIME endDate;
|
||||
DateDifference dateDiff;
|
||||
} DateTimeTestCase;
|
||||
|
||||
SYSTEMTIME date[c_numDate];
|
||||
DateDifference dateDifference[c_dateDiff];
|
||||
DateTimeTestCase datetimeDifftest[c_diffTestCase];
|
||||
DateTimeTestCase datetimeBoundAdd[c_numAddOobDate];
|
||||
DateTimeTestCase datetimeBoundSubtract[c_numSubtractOobDate];
|
||||
DateTimeTestCase datetimeAddCase[c_addCases];
|
||||
DateTimeTestCase datetimeSubtractCase[c_subtractCases];
|
||||
|
||||
|
||||
// Test Class
|
||||
class DateCalculatorUnitTests
|
||||
{
|
||||
public:
|
||||
TEST_CLASS(DateCalculatorUnitTests);
|
||||
|
||||
TEST_CLASS_SETUP(TestClassSetup)
|
||||
{
|
||||
/* Test Case Data */
|
||||
|
||||
// Dates - DD.MM.YYYY
|
||||
/*31.12.9999*/ date[0].wYear = 9999; date[0].wMonth = 12; date[0].wDayOfWeek = 5; date[0].wDay = 31; date[0].wHour = 0; date[0].wMinute = 0; date[0].wSecond = 0; date[0].wMilliseconds = 0;
|
||||
/*30.12.9999*/ date[1].wYear = 9999; date[1].wMonth = 12; date[1].wDayOfWeek = 4; date[1].wDay = 30; date[1].wHour = 0; date[1].wMinute = 0; date[1].wSecond = 0; date[1].wMilliseconds = 0;
|
||||
/*31.12.9998*/ date[2].wYear = 9998; date[2].wMonth = 12; date[2].wDayOfWeek = 4; date[2].wDay = 31; date[2].wHour = 0; date[2].wMinute = 0; date[2].wSecond = 0; date[2].wMilliseconds = 0;
|
||||
/*01.01.1601*/ date[3].wYear = 1601; date[3].wMonth = 1; date[3].wDayOfWeek = 1; date[3].wDay = 1; date[3].wHour = 0; date[3].wMinute = 0; date[3].wSecond = 0; date[3].wMilliseconds = 0;
|
||||
/*02.01.1601*/ date[4].wYear = 1601; date[4].wMonth = 1; date[4].wDayOfWeek = 2; date[4].wDay = 2; date[4].wHour = 0; date[4].wMinute = 0; date[4].wSecond = 0; date[4].wMilliseconds = 0;
|
||||
/*10.05.2008*/ date[5].wYear = 2008; date[5].wMonth = 5; date[5].wDayOfWeek = 6; date[5].wDay = 10; date[5].wHour = 0; date[5].wMinute = 0; date[5].wSecond = 0; date[5].wMilliseconds = 0;
|
||||
/*10.03.2008*/ date[6].wYear = 2008; date[6].wMonth = 3; date[6].wDayOfWeek = 1; date[6].wDay = 10; date[6].wHour = 0; date[6].wMinute = 0; date[6].wSecond = 0; date[6].wMilliseconds = 0;
|
||||
/*29.02.2008*/ date[7].wYear = 2008; date[7].wMonth = 2; date[7].wDayOfWeek = 5; date[7].wDay = 29; date[7].wHour = 0; date[7].wMinute = 0; date[7].wSecond = 0; date[7].wMilliseconds = 0;
|
||||
/*28.02.2007*/ date[8].wYear = 2007; date[8].wMonth = 2; date[8].wDayOfWeek = 3; date[8].wDay = 28; date[8].wHour = 0; date[8].wMinute = 0; date[8].wSecond = 0; date[8].wMilliseconds = 0;
|
||||
/*10.03.2007*/ date[9].wYear = 2007; date[9].wMonth = 3; date[9].wDayOfWeek = 6; date[9].wDay = 10; date[9].wHour = 0; date[9].wMinute = 0; date[9].wSecond = 0; date[9].wMilliseconds = 0;
|
||||
/*10.05.2007*/ date[10].wYear = 2007; date[10].wMonth = 5; date[10].wDayOfWeek = 4; date[10].wDay = 10; date[10].wHour = 0; date[10].wMinute = 0; date[10].wSecond = 0; date[10].wMilliseconds = 0;
|
||||
/*29.01.2008*/ date[11].wYear = 2008; date[11].wMonth = 1; date[11].wDayOfWeek = 2; date[11].wDay = 29; date[11].wHour = 0; date[11].wMinute = 0; date[11].wSecond = 0; date[11].wMilliseconds = 0;
|
||||
/*28.01.2007*/ date[12].wYear = 2007; date[12].wMonth = 1; date[12].wDayOfWeek = 0; date[12].wDay = 28; date[12].wHour = 0; date[12].wMinute = 0; date[12].wSecond = 0; date[12].wMilliseconds = 0;
|
||||
/*31.01.2008*/ date[13].wYear = 2008; date[13].wMonth = 1; date[13].wDayOfWeek = 4; date[13].wDay = 31; date[13].wHour = 0; date[13].wMinute = 0; date[13].wSecond = 0; date[13].wMilliseconds = 0;
|
||||
/*31.03.2008*/ date[14].wYear = 2008; date[14].wMonth = 3; date[14].wDayOfWeek = 1; date[14].wDay = 31; date[14].wHour = 0; date[14].wMinute = 0; date[14].wSecond = 0; date[14].wMilliseconds = 0;
|
||||
|
||||
// Date Differences
|
||||
dateDifference[0].year = 1; dateDifference[0].month = 1;
|
||||
dateDifference[1].month = 1; dateDifference[1].day = 10;
|
||||
dateDifference[2].day = 2;
|
||||
/*date[2]-[0]*/ dateDifference[3].week = 52; dateDifference[3].day = 1;
|
||||
/*date[2]-[0]*/ dateDifference[4].year = 1;
|
||||
dateDifference[5].day = 365;
|
||||
dateDifference[6].month = 1;
|
||||
dateDifference[7].month = 1; dateDifference[7].day = 2;
|
||||
dateDifference[8].day = 31;
|
||||
dateDifference[9].month = 11; dateDifference[9].day = 1;
|
||||
dateDifference[10].year = 8398; dateDifference[10].month = 11; dateDifference[10].day = 30;
|
||||
dateDifference[11].year = 2008;
|
||||
dateDifference[12].year = 7991; dateDifference[12].month = 11;
|
||||
dateDifference[13].week = 416998; dateDifference[13].day = 1;
|
||||
|
||||
|
||||
|
||||
/* Test Cases */
|
||||
|
||||
// Date Difference test cases
|
||||
datetimeDifftest[0].startDate = date[0]; datetimeDifftest[0].endDate = date[3]; datetimeDifftest[0].dateDiff = dateDifference[10];
|
||||
datetimeDifftest[1].startDate = date[0]; datetimeDifftest[1].endDate = date[2]; datetimeDifftest[1].dateDiff = dateDifference[5];
|
||||
datetimeDifftest[2].startDate = date[0]; datetimeDifftest[2].endDate = date[2]; datetimeDifftest[2].dateDiff = dateDifference[4];
|
||||
datetimeDifftest[3].startDate = date[0]; datetimeDifftest[3].endDate = date[2]; datetimeDifftest[3].dateDiff = dateDifference[3];
|
||||
datetimeDifftest[4].startDate = date[14]; datetimeDifftest[4].endDate = date[7]; datetimeDifftest[4].dateDiff = dateDifference[7];
|
||||
datetimeDifftest[5].startDate = date[14]; datetimeDifftest[5].endDate = date[7]; datetimeDifftest[5].dateDiff = dateDifference[8];
|
||||
datetimeDifftest[6].startDate = date[11]; datetimeDifftest[6].endDate = date[8]; datetimeDifftest[6].dateDiff = dateDifference[9];
|
||||
datetimeDifftest[7].startDate = date[13]; datetimeDifftest[7].endDate = date[0]; datetimeDifftest[7].dateDiff = dateDifference[12];
|
||||
datetimeDifftest[8].startDate = date[13]; datetimeDifftest[8].endDate = date[0]; datetimeDifftest[8].dateDiff = dateDifference[13];
|
||||
|
||||
// Date Add Out of Bound test cases (Negative tests)
|
||||
/*OutofBound*/ datetimeBoundAdd[0].startDate = date[1]; datetimeBoundAdd[0].endDate = date[0]; datetimeBoundAdd[0].dateDiff = dateDifference[2]; // on Add date[0] not used
|
||||
/*OutofBound*/ datetimeBoundAdd[1].startDate = date[2]; datetimeBoundAdd[1].endDate = date[0]; datetimeBoundAdd[1].dateDiff = dateDifference[11]; // on Add date[0] not used
|
||||
|
||||
// Date Subtract Out of Bound test cases (Negative tests)
|
||||
/*OutofBound*/ datetimeBoundSubtract[0].startDate = date[3]; datetimeBoundSubtract[0].endDate = date[0]; datetimeBoundSubtract[0].dateDiff = dateDifference[2]; // on subtract date[0] not used
|
||||
/*OutofBound*/ datetimeBoundSubtract[1].startDate = date[14]; datetimeBoundSubtract[1].endDate = date[0]; datetimeBoundSubtract[1].dateDiff = dateDifference[11]; // on subtract date[0] not used
|
||||
|
||||
// Date Add test cases (Positive tests)
|
||||
datetimeAddCase[0].startDate = date[13]; datetimeAddCase[0].endDate = date[7]; datetimeAddCase[0].dateDiff = dateDifference[6];// add
|
||||
datetimeAddCase[1].startDate = date[14]; datetimeAddCase[1].endDate = date[5]; datetimeAddCase[1].dateDiff = dateDifference[1];// add
|
||||
datetimeAddCase[2].startDate = date[13]; datetimeAddCase[2].endDate = date[6]; datetimeAddCase[2].dateDiff = dateDifference[1];// add
|
||||
|
||||
// Date Subtract test cases (Positive tests)
|
||||
datetimeSubtractCase[0].startDate = date[14]; datetimeSubtractCase[0].endDate = date[7]; datetimeSubtractCase[0].dateDiff = dateDifference[6];// subtract
|
||||
datetimeSubtractCase[1].startDate = date[6]; datetimeSubtractCase[1].endDate = date[11]; datetimeSubtractCase[1].dateDiff = dateDifference[1];// subtract
|
||||
datetimeSubtractCase[2].startDate = date[9]; datetimeSubtractCase[2].endDate = date[12]; datetimeSubtractCase[2].dateDiff = dateDifference[1];// subtract
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Duration Between Two Date Tests -- Timediff obtained after calculation should be checked to be identical */
|
||||
TEST_METHOD(TestDateDiff)
|
||||
{
|
||||
// TODO - MSFT 10331900, fix this test
|
||||
|
||||
//for (int testIndex = 0; testIndex < c_diffTestCase; testIndex++)
|
||||
//{
|
||||
// DateDifference diff;
|
||||
// DateUnit dateOutputFormat;
|
||||
|
||||
// switch (testIndex)
|
||||
// {
|
||||
// case 0:
|
||||
// case 2:
|
||||
// dateOutputFormat = DateUnit::Year | DateUnit::Month | DateUnit::Day;
|
||||
// break;
|
||||
// case 1:
|
||||
// dateOutputFormat = DateUnit::Day;
|
||||
// break;
|
||||
// case 3:
|
||||
// case 8:
|
||||
// dateOutputFormat = DateUnit::Week | DateUnit::Day;
|
||||
// break;
|
||||
// case 7:
|
||||
// dateOutputFormat = DateUnit::Year | DateUnit::Month | DateUnit::Day;
|
||||
// break;
|
||||
// case 4:
|
||||
// case 6:
|
||||
// dateOutputFormat = DateUnit::Month | DateUnit::Day;
|
||||
// break;
|
||||
// case 5:
|
||||
// dateOutputFormat = DateUnit::Day;
|
||||
// break;
|
||||
// }
|
||||
|
||||
// // Calculate the difference
|
||||
// m_DateCalcEngine.GetDateDifference(DateUtils::SystemTimeToDateTime(datetimeDifftest[testIndex].startDate), DateUtils::SystemTimeToDateTime(datetimeDifftest[testIndex].endDate), dateOutputFormat, &diff);
|
||||
|
||||
// // Assert for the result
|
||||
// bool areIdentical = true;
|
||||
// if (diff.year != datetimeDifftest[testIndex].dateDiff.year ||
|
||||
// diff.month != datetimeDifftest[testIndex].dateDiff.month ||
|
||||
// diff.week != datetimeDifftest[testIndex].dateDiff.week ||
|
||||
// diff.day != datetimeDifftest[testIndex].dateDiff.day)
|
||||
// {
|
||||
// areIdentical = false;
|
||||
// }
|
||||
|
||||
// VERIFY_IS_TRUE(areIdentical);
|
||||
//}
|
||||
}
|
||||
|
||||
/*Add Out of bound Tests*/
|
||||
TEST_METHOD(TestAddOob)
|
||||
{
|
||||
// TODO - MSFT 10331900, fix this test
|
||||
|
||||
//for (int testIndex = 0; testIndex< c_numAddOobDate; testIndex++)
|
||||
//{
|
||||
// DateTime endDate;
|
||||
|
||||
// // Add Duration
|
||||
// bool isValid = m_DateCalcEngine.AddDuration(DateUtils::SystemTimeToDateTime(datetimeBoundAdd[testIndex].startDate), datetimeBoundAdd[testIndex].dateDiff, &endDate);
|
||||
|
||||
// // Assert for the result
|
||||
// VERIFY_IS_FALSE(isValid);
|
||||
//}
|
||||
}
|
||||
|
||||
/*Subtract Out of bound Tests*/
|
||||
TEST_METHOD(TestSubtractOob)
|
||||
{
|
||||
for (int testIndex = 0; testIndex< c_numSubtractOobDate; testIndex++)
|
||||
{
|
||||
DateTime endDate;
|
||||
|
||||
// Subtract Duration
|
||||
bool isValid = m_DateCalcEngine.SubtractDuration(DateUtils::SystemTimeToDateTime(datetimeBoundSubtract[testIndex].startDate), datetimeBoundSubtract[testIndex].dateDiff, &endDate);
|
||||
|
||||
// Assert for the result
|
||||
VERIFY_IS_FALSE(isValid);
|
||||
}
|
||||
}
|
||||
|
||||
// Add Tests
|
||||
TEST_METHOD(TestAddition)
|
||||
{
|
||||
// TODO - MSFT 10331900, fix this test
|
||||
|
||||
//for (int testIndex = 0; testIndex < c_addCases; testIndex++)
|
||||
//{
|
||||
// DateTime endDate;
|
||||
|
||||
// // Add Duration
|
||||
// bool isValid = m_DateCalcEngine.AddDuration(DateUtils::SystemTimeToDateTime(datetimeAddCase[testIndex].startDate), datetimeAddCase[testIndex].dateDiff, &endDate);
|
||||
|
||||
// // Assert for the result
|
||||
// VERIFY_IS_TRUE(isValid);
|
||||
|
||||
// SYSTEMTIME systemTime = DateUtils::DateTimeToSystemTime(endDate);
|
||||
// if (systemTime.wYear != datetimeAddCase[testIndex].endDate.wYear ||
|
||||
// systemTime.wMonth != datetimeAddCase[testIndex].endDate.wMonth ||
|
||||
// systemTime.wDay != datetimeAddCase[testIndex].endDate.wDay ||
|
||||
// systemTime.wDayOfWeek != datetimeAddCase[testIndex].endDate.wDayOfWeek)
|
||||
// {
|
||||
// isValid = false;
|
||||
// }
|
||||
|
||||
// VERIFY_IS_TRUE(isValid);
|
||||
//}
|
||||
}
|
||||
|
||||
// Subtract Tests
|
||||
TEST_METHOD(TestSubtraction)
|
||||
{
|
||||
// TODO - MSFT 10331900, fix this test
|
||||
|
||||
//for (int testIndex = 0; testIndex < c_subtractCases; testIndex++)
|
||||
//{
|
||||
// DateTime endDate;
|
||||
|
||||
// // Subtract Duration
|
||||
// bool isValid = m_DateCalcEngine.SubtractDuration(DateUtils::SystemTimeToDateTime(datetimeSubtractCase[testIndex].startDate), datetimeSubtractCase[testIndex].dateDiff, &endDate);
|
||||
|
||||
// // assert for the result
|
||||
// VERIFY_IS_TRUE(isValid);
|
||||
|
||||
// SYSTEMTIME systemTime = DateUtils::DateTimeToSystemTime(endDate);
|
||||
// if (systemTime.wYear != datetimeSubtractCase[testIndex].endDate.wYear ||
|
||||
// systemTime.wMonth != datetimeSubtractCase[testIndex].endDate.wMonth ||
|
||||
// systemTime.wDay != datetimeSubtractCase[testIndex].endDate.wDay ||
|
||||
// systemTime.wDayOfWeek != datetimeSubtractCase[testIndex].endDate.wDayOfWeek)
|
||||
// {
|
||||
// isValid = false;
|
||||
// }
|
||||
|
||||
// VERIFY_IS_TRUE(isValid);
|
||||
//}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
class DateCalculatorViewModelTests
|
||||
{
|
||||
public:
|
||||
TEST_CLASS(DateCalculatorViewModelTests);
|
||||
|
||||
TEST_CLASS_SETUP(TestClassSetup)
|
||||
{
|
||||
/* Test Case Data */
|
||||
|
||||
// Dates - DD.MM.YYYY
|
||||
/*31.12.9999*/ date[0].wYear = 9999; date[0].wMonth = 12; date[0].wDayOfWeek = 5; date[0].wDay = 31; date[0].wHour = 0; date[0].wMinute = 0; date[0].wSecond = 0; date[0].wMilliseconds = 0;
|
||||
/*30.12.9999*/ date[1].wYear = 9999; date[1].wMonth = 12; date[1].wDayOfWeek = 4; date[1].wDay = 30; date[1].wHour = 0; date[1].wMinute = 0; date[1].wSecond = 0; date[1].wMilliseconds = 0;
|
||||
/*31.12.9998*/ date[2].wYear = 9998; date[2].wMonth = 12; date[2].wDayOfWeek = 4; date[2].wDay = 31; date[2].wHour = 0; date[2].wMinute = 0; date[2].wSecond = 0; date[2].wMilliseconds = 0;
|
||||
/*01.01.1601*/ date[3].wYear = 1601; date[3].wMonth = 1; date[3].wDayOfWeek = 1; date[3].wDay = 1; date[3].wHour = 0; date[3].wMinute = 0; date[3].wSecond = 0; date[3].wMilliseconds = 0;
|
||||
/*02.01.1601*/ date[4].wYear = 1601; date[4].wMonth = 1; date[4].wDayOfWeek = 2; date[4].wDay = 2; date[4].wHour = 0; date[4].wMinute = 0; date[4].wSecond = 0; date[4].wMilliseconds = 0;
|
||||
/*10.05.2008*/ date[5].wYear = 2008; date[5].wMonth = 5; date[5].wDayOfWeek = 6; date[5].wDay = 10; date[5].wHour = 0; date[5].wMinute = 0; date[5].wSecond = 0; date[5].wMilliseconds = 0;
|
||||
/*10.03.2008*/ date[6].wYear = 2008; date[6].wMonth = 3; date[6].wDayOfWeek = 1; date[6].wDay = 10; date[6].wHour = 0; date[6].wMinute = 0; date[6].wSecond = 0; date[6].wMilliseconds = 0;
|
||||
/*29.02.2008*/ date[7].wYear = 2008; date[7].wMonth = 2; date[7].wDayOfWeek = 5; date[7].wDay = 29; date[7].wHour = 0; date[7].wMinute = 0; date[7].wSecond = 0; date[7].wMilliseconds = 0;
|
||||
/*28.02.2007*/ date[8].wYear = 2007; date[8].wMonth = 2; date[8].wDayOfWeek = 3; date[8].wDay = 28; date[8].wHour = 0; date[8].wMinute = 0; date[8].wSecond = 0; date[8].wMilliseconds = 0;
|
||||
/*10.03.2007*/ date[9].wYear = 2007; date[9].wMonth = 3; date[9].wDayOfWeek = 6; date[9].wDay = 10; date[9].wHour = 0; date[9].wMinute = 0; date[9].wSecond = 0; date[9].wMilliseconds = 0;
|
||||
/*10.05.2007*/ date[10].wYear = 2007; date[10].wMonth = 5; date[10].wDayOfWeek = 4; date[10].wDay = 10; date[10].wHour = 0; date[10].wMinute = 0; date[10].wSecond = 0; date[10].wMilliseconds = 0;
|
||||
/*29.01.2008*/ date[11].wYear = 2008; date[11].wMonth = 1; date[11].wDayOfWeek = 2; date[11].wDay = 29; date[11].wHour = 0; date[11].wMinute = 0; date[11].wSecond = 0; date[11].wMilliseconds = 0;
|
||||
/*28.01.2007*/ date[12].wYear = 2007; date[12].wMonth = 1; date[12].wDayOfWeek = 0; date[12].wDay = 28; date[12].wHour = 0; date[12].wMinute = 0; date[12].wSecond = 0; date[12].wMilliseconds = 0;
|
||||
/*31.01.2008*/ date[13].wYear = 2008; date[13].wMonth = 1; date[13].wDayOfWeek = 4; date[13].wDay = 31; date[13].wHour = 0; date[13].wMinute = 0; date[13].wSecond = 0; date[13].wMilliseconds = 0;
|
||||
/*31.03.2008*/ date[14].wYear = 2008; date[14].wMonth = 3; date[14].wDayOfWeek = 1; date[14].wDay = 31; date[14].wHour = 0; date[14].wMinute = 0; date[14].wSecond = 0; date[14].wMilliseconds = 0;
|
||||
|
||||
// Date Differences
|
||||
dateDifference[0].year = 1; dateDifference[0].month = 1;
|
||||
dateDifference[1].month = 1; dateDifference[1].day = 10;
|
||||
dateDifference[2].day = 2;
|
||||
/*date[2]-[0]*/ dateDifference[3].week = 52; dateDifference[3].day = 1;
|
||||
/*date[2]-[0]*/ dateDifference[4].year = 1;
|
||||
dateDifference[5].day = 365;
|
||||
dateDifference[6].month = 1;
|
||||
dateDifference[7].month = 1; dateDifference[7].day = 2;
|
||||
dateDifference[8].day = 31;
|
||||
dateDifference[9].month = 11; dateDifference[9].day = 1;
|
||||
dateDifference[10].year = 8398; dateDifference[10].month = 11; dateDifference[10].day = 30;
|
||||
dateDifference[11].year = 2008;
|
||||
dateDifference[12].year = 7991; dateDifference[12].month = 11;
|
||||
dateDifference[13].week = 416998; dateDifference[13].day = 1;
|
||||
|
||||
|
||||
|
||||
/* Test Cases */
|
||||
|
||||
// Date Difference test cases
|
||||
datetimeDifftest[0].startDate = date[0]; datetimeDifftest[0].endDate = date[3]; datetimeDifftest[0].dateDiff = dateDifference[10];
|
||||
datetimeDifftest[1].startDate = date[0]; datetimeDifftest[1].endDate = date[2]; datetimeDifftest[1].dateDiff = dateDifference[5];
|
||||
datetimeDifftest[2].startDate = date[0]; datetimeDifftest[2].endDate = date[2]; datetimeDifftest[2].dateDiff = dateDifference[4];
|
||||
datetimeDifftest[3].startDate = date[0]; datetimeDifftest[3].endDate = date[2]; datetimeDifftest[3].dateDiff = dateDifference[3];
|
||||
datetimeDifftest[4].startDate = date[14]; datetimeDifftest[4].endDate = date[7]; datetimeDifftest[4].dateDiff = dateDifference[7];
|
||||
datetimeDifftest[5].startDate = date[14]; datetimeDifftest[5].endDate = date[7]; datetimeDifftest[5].dateDiff = dateDifference[8];
|
||||
datetimeDifftest[6].startDate = date[11]; datetimeDifftest[6].endDate = date[8]; datetimeDifftest[6].dateDiff = dateDifference[9];
|
||||
datetimeDifftest[7].startDate = date[13]; datetimeDifftest[7].endDate = date[0]; datetimeDifftest[7].dateDiff = dateDifference[12];
|
||||
datetimeDifftest[8].startDate = date[13]; datetimeDifftest[8].endDate = date[0]; datetimeDifftest[8].dateDiff = dateDifference[13];
|
||||
|
||||
// Date Add Out of Bound test cases (Negative tests)
|
||||
/*OutofBound*/ datetimeBoundAdd[0].startDate = date[1]; datetimeBoundAdd[0].endDate = date[0]; datetimeBoundAdd[0].dateDiff = dateDifference[2]; // on Add date[0] not used
|
||||
/*OutofBound*/ datetimeBoundAdd[1].startDate = date[2]; datetimeBoundAdd[1].endDate = date[0]; datetimeBoundAdd[1].dateDiff = dateDifference[11]; // on Add date[0] not used
|
||||
|
||||
// Date Subtract Out of Bound test cases (Negative tests)
|
||||
/*OutofBound*/ datetimeBoundSubtract[0].startDate = date[3]; datetimeBoundSubtract[0].endDate = date[0]; datetimeBoundSubtract[0].dateDiff = dateDifference[2]; // on subtract date[0] not used
|
||||
/*OutofBound*/ datetimeBoundSubtract[1].startDate = date[14]; datetimeBoundSubtract[1].endDate = date[0]; datetimeBoundSubtract[1].dateDiff = dateDifference[11]; // on subtract date[0] not used
|
||||
|
||||
// Date Add test cases (Positive tests)
|
||||
datetimeAddCase[0].startDate = date[13]; datetimeAddCase[0].endDate = date[7]; datetimeAddCase[0].dateDiff = dateDifference[6];// add
|
||||
datetimeAddCase[1].startDate = date[14]; datetimeAddCase[1].endDate = date[5]; datetimeAddCase[1].dateDiff = dateDifference[1];// add
|
||||
datetimeAddCase[2].startDate = date[13]; datetimeAddCase[2].endDate = date[6]; datetimeAddCase[2].dateDiff = dateDifference[1];// add
|
||||
|
||||
// Date Subtract test cases (Positive tests)
|
||||
datetimeSubtractCase[0].startDate = date[14]; datetimeSubtractCase[0].endDate = date[7]; datetimeSubtractCase[0].dateDiff = dateDifference[6];// subtract
|
||||
datetimeSubtractCase[1].startDate = date[6]; datetimeSubtractCase[1].endDate = date[11]; datetimeSubtractCase[1].dateDiff = dateDifference[1];// subtract
|
||||
datetimeSubtractCase[2].startDate = date[9]; datetimeSubtractCase[2].endDate = date[12]; datetimeSubtractCase[2].dateDiff = dateDifference[1];// subtract
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST_METHOD(DateCalcViewModelInitializationTest)
|
||||
{
|
||||
auto viewModel = ref new DateCalculatorViewModel();
|
||||
|
||||
// Check for the initialized values
|
||||
VERIFY_IS_TRUE(viewModel->IsDateDiffMode);
|
||||
VERIFY_IS_TRUE(viewModel->IsAddMode);
|
||||
|
||||
VERIFY_IS_TRUE(0 != viewModel->FromDate.UniversalTime);
|
||||
VERIFY_IS_TRUE(0 != viewModel->ToDate.UniversalTime);
|
||||
VERIFY_IS_TRUE(0 != viewModel->StartDate.UniversalTime);
|
||||
|
||||
VERIFY_ARE_EQUAL(0, viewModel->DaysOffset);
|
||||
VERIFY_ARE_EQUAL(0, viewModel->MonthsOffset);
|
||||
VERIFY_ARE_EQUAL(0, viewModel->YearsOffset);
|
||||
|
||||
VERIFY_IS_TRUE(viewModel->IsDiffInDays);
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Same dates"), viewModel->StrDateDiffResult);
|
||||
VERIFY_IS_NULL(viewModel->StrDateDiffResultInDays);
|
||||
|
||||
VERIFY_IS_NULL(viewModel->StrDateResult);
|
||||
}
|
||||
|
||||
TEST_METHOD(DateCalcViewModelAddSubtractInitTest)
|
||||
{
|
||||
auto viewModel = ref new DateCalculatorViewModel();
|
||||
viewModel->IsDateDiffMode = false;
|
||||
|
||||
// Check for the initialized values
|
||||
VERIFY_IS_FALSE(viewModel->IsDateDiffMode);
|
||||
VERIFY_IS_TRUE(viewModel->IsAddMode);
|
||||
|
||||
VERIFY_IS_TRUE(0 != viewModel->FromDate.UniversalTime);
|
||||
VERIFY_IS_TRUE(0 != viewModel->ToDate.UniversalTime);
|
||||
VERIFY_IS_TRUE(0 != viewModel->StartDate.UniversalTime);
|
||||
|
||||
VERIFY_ARE_EQUAL(0, viewModel->DaysOffset);
|
||||
VERIFY_ARE_EQUAL(0, viewModel->MonthsOffset);
|
||||
VERIFY_ARE_EQUAL(0, viewModel->YearsOffset);
|
||||
|
||||
VERIFY_IS_TRUE(viewModel->IsDiffInDays);
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Same dates"), viewModel->StrDateDiffResult);
|
||||
VERIFY_IS_NULL(viewModel->StrDateDiffResultInDays);
|
||||
|
||||
VERIFY_IS_NOT_NULL(viewModel->StrDateResult);
|
||||
VERIFY_IS_TRUE(StringReference(L"") != viewModel->StrDateResult);
|
||||
}
|
||||
|
||||
TEST_METHOD(DateCalcViewModelAddTest)
|
||||
{
|
||||
// TODO - MSFT 10331900, fix this test
|
||||
// A few issues to be investigated..
|
||||
// The date returned by DateUtils::GetLongDate can be a different string than expected
|
||||
// based on the values of date[7]. This is because date[7] is in UTC but GetLongDate
|
||||
// doesn't format according to UTC. If it did, the test would still be incorrect because
|
||||
// the ViewModel is not necessarily in UTC.
|
||||
//
|
||||
// The DateTime value assigned to StartDate after the conversion SystemTimeToDateTime is not
|
||||
// the same DateTime value as if the user were to select the same date from the CalendarDatePicker.
|
||||
// This means testing a specific date here, is *not* the same as selecting that date in the app.
|
||||
|
||||
//auto viewModel = ref new DateCalculatorViewModel();
|
||||
//viewModel->Initialize();
|
||||
|
||||
//viewModel->IsDateDiffMode = false;
|
||||
//viewModel->IsAddMode = true;
|
||||
//VERIFY_IS_FALSE(viewModel->IsDateDiffMode);
|
||||
//VERIFY_IS_TRUE(viewModel->IsAddMode);
|
||||
|
||||
//viewModel->StartDate = DateUtils::SystemTimeToDateTime(datetimeAddCase[0].startDate);
|
||||
//viewModel->DaysOffset = datetimeAddCase[0].dateDiff.day;
|
||||
//viewModel->MonthsOffset = datetimeAddCase[0].dateDiff.month;
|
||||
//viewModel->YearsOffset = datetimeAddCase[0].dateDiff.year;
|
||||
|
||||
//// Assert for the result
|
||||
//VERIFY_ARE_EQUAL(DateUtils::GetLongDate(date[7]), viewModel->StrDateResult);
|
||||
}
|
||||
|
||||
TEST_METHOD(DateCalcViewModelSubtractTest)
|
||||
{
|
||||
// TODO - MSFT 10331900, fix this test
|
||||
// A few issues to be investigated..
|
||||
// The date returned by DateUtils::GetLongDate can be a different string than expected
|
||||
// based on the values of date[7]. This is because date[7] is in UTC but GetLongDate
|
||||
// doesn't format according to UTC. If it did, the test would still be incorrect because
|
||||
// the ViewModel is not necessarily in UTC.
|
||||
//
|
||||
// The DateTime value assigned to StartDate after the conversion SystemTimeToDateTime is not
|
||||
// the same DateTime value as if the user were to select the same date from the CalendarDatePicker.
|
||||
// This means testing a specific date here, is *not* the same as selecting that date in the app.
|
||||
|
||||
//auto viewModel = ref new DateCalculatorViewModel();
|
||||
//viewModel->Initialize();
|
||||
|
||||
//viewModel->IsDateDiffMode = false;
|
||||
//viewModel->IsAddMode = false;
|
||||
//VERIFY_IS_FALSE(viewModel->IsDateDiffMode);
|
||||
//VERIFY_IS_FALSE(viewModel->IsAddMode);
|
||||
|
||||
//viewModel->StartDate = DateUtils::SystemTimeToDateTime(datetimeSubtractCase[0].startDate);
|
||||
//viewModel->DaysOffset = datetimeSubtractCase[0].dateDiff.day;
|
||||
//viewModel->MonthsOffset = datetimeSubtractCase[0].dateDiff.month;
|
||||
//viewModel->YearsOffset = datetimeSubtractCase[0].dateDiff.year;
|
||||
|
||||
//// Assert for the result
|
||||
//VERIFY_ARE_EQUAL(DateUtils::GetLongDate(date[7]), viewModel->StrDateResult);
|
||||
}
|
||||
|
||||
TEST_METHOD(DateCalcViewModelAddOobTest)
|
||||
{
|
||||
// TODO - MSFT 10331900, fix this test
|
||||
// Curiously enough, this test fails because it fails to go Oob.
|
||||
// Possibly need to update test to use a new max date.
|
||||
|
||||
//auto viewModel = ref new DateCalculatorViewModel();
|
||||
//viewModel->Initialize();
|
||||
|
||||
//viewModel->IsDateDiffMode = false;
|
||||
//viewModel->IsAddMode = true;
|
||||
//VERIFY_IS_FALSE(viewModel->IsDateDiffMode);
|
||||
//VERIFY_IS_TRUE(viewModel->IsAddMode);
|
||||
|
||||
//for (int testIndex = 0; testIndex< c_numAddOobDate; testIndex++)
|
||||
//{
|
||||
// viewModel->StartDate = DateUtils::SystemTimeToDateTime(datetimeBoundAdd[testIndex].startDate);
|
||||
// viewModel->DaysOffset = datetimeBoundAdd[testIndex].dateDiff.day;
|
||||
// viewModel->MonthsOffset = datetimeBoundAdd[testIndex].dateDiff.month;
|
||||
// viewModel->YearsOffset = datetimeBoundAdd[testIndex].dateDiff.year;
|
||||
|
||||
// // Assert for the result
|
||||
// VERIFY_ARE_EQUAL(StringReference(L"Date out of Bound"), viewModel->StrDateResult);
|
||||
//}
|
||||
}
|
||||
|
||||
TEST_METHOD(DateCalcViewModelSubtractOobTest)
|
||||
{
|
||||
auto viewModel = ref new DateCalculatorViewModel();
|
||||
|
||||
viewModel->IsDateDiffMode = false;
|
||||
viewModel->IsAddMode = false;
|
||||
VERIFY_IS_FALSE(viewModel->IsDateDiffMode);
|
||||
VERIFY_IS_FALSE(viewModel->IsAddMode);
|
||||
|
||||
for (int testIndex = 0; testIndex < c_numSubtractOobDate; testIndex++)
|
||||
{
|
||||
viewModel->StartDate = DateUtils::SystemTimeToDateTime(datetimeBoundSubtract[testIndex].startDate);
|
||||
viewModel->DaysOffset = datetimeBoundSubtract[testIndex].dateDiff.day;
|
||||
viewModel->MonthsOffset = datetimeBoundSubtract[testIndex].dateDiff.month;
|
||||
viewModel->YearsOffset = datetimeBoundSubtract[testIndex].dateDiff.year;
|
||||
|
||||
// Assert for the result
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Date out of Bound"), viewModel->StrDateResult);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_METHOD(DateCalcViewModelDateDiffTest)
|
||||
{
|
||||
// TODO - MSFT 10331900, fix this test
|
||||
// The last VERIFY checks with expected value "8398 years, 11 months, 4 weeks, 2 days"
|
||||
// The viewmodel result is something like "8398 years, 12 months, 6568892 weeks, 1 day",
|
||||
// which shows there is a problem with the viewmodel's reduction algorithm.
|
||||
|
||||
//auto viewModel = ref new DateCalculatorViewModel();
|
||||
//viewModel->Initialize();
|
||||
|
||||
//viewModel->IsDateDiffMode = true;
|
||||
//VERIFY_IS_TRUE(viewModel->IsDateDiffMode);
|
||||
|
||||
//viewModel->FromDate = DateUtils::SystemTimeToDateTime(datetimeDifftest[0].startDate);
|
||||
//viewModel->ToDate = DateUtils::SystemTimeToDateTime(datetimeDifftest[0].endDate);
|
||||
|
||||
//// Assert for the result
|
||||
//VERIFY_IS_FALSE(viewModel->IsDiffInDays);
|
||||
//VERIFY_ARE_EQUAL(StringReference(L"3067670 days"), viewModel->StrDateDiffResultInDays);
|
||||
//VERIFY_ARE_EQUAL(StringReference(L"8398 years, 11 months, 4 weeks, 2 days"), viewModel->StrDateDiffResult);
|
||||
}
|
||||
|
||||
TEST_METHOD(DateCalcViewModelDateDiffResultInDaysTest)
|
||||
{
|
||||
auto viewModel = ref new DateCalculatorViewModel();
|
||||
|
||||
viewModel->IsDateDiffMode = true;
|
||||
VERIFY_IS_TRUE(viewModel->IsDateDiffMode);
|
||||
|
||||
viewModel->FromDate = DateUtils::SystemTimeToDateTime(date[0]);
|
||||
viewModel->ToDate = DateUtils::SystemTimeToDateTime(date[1]);
|
||||
|
||||
// Assert for the result
|
||||
VERIFY_IS_TRUE(viewModel->IsDiffInDays);
|
||||
VERIFY_ARE_EQUAL(StringReference(L"1 day"), viewModel->StrDateDiffResult);
|
||||
VERIFY_IS_NULL(viewModel->StrDateDiffResultInDays);
|
||||
}
|
||||
|
||||
// Tests that the automation name for the resulting date in Add Mode
|
||||
// contains the DayOfWeek, Day, Month, and Year
|
||||
TEST_METHOD(DateCalcViewModelAddSubtractResultAutomationNameTest)
|
||||
{
|
||||
auto viewModel = ref new DateCalculatorViewModel();
|
||||
|
||||
auto cal = ref new Calendar();
|
||||
cal->Year = 2007;
|
||||
cal->Month = 5;
|
||||
cal->Day = 10;
|
||||
cal->Hour = 12;
|
||||
cal->Period = 2;
|
||||
cal->Nanosecond = 0;
|
||||
cal->Second = 0;
|
||||
|
||||
DateTime startDate = cal->GetDateTime();
|
||||
viewModel->StartDate = startDate;
|
||||
|
||||
viewModel->IsDateDiffMode = false;
|
||||
viewModel->IsAddMode = true;
|
||||
|
||||
wstring actualValue = viewModel->StrDateResultAutomationName->Data();
|
||||
|
||||
// Verify each component is present in the result
|
||||
wstring components[] = {
|
||||
L"dayofweek.full",
|
||||
L"month.full",
|
||||
L"year.full",
|
||||
L"day"
|
||||
};
|
||||
|
||||
for (const wstring &component : components)
|
||||
{
|
||||
auto formatter = ref new DateTimeFormatter(ref new String(component.c_str()));
|
||||
wstring expectedValue = formatter->Format(startDate)->Data();
|
||||
wstring message = L"Verifying " + component + L" is present in the result";
|
||||
VERIFY_IS_TRUE(actualValue.find(expectedValue) != wstring::npos, message.c_str());
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
56
internal/CalculatorUnitTests/DateUtils.h
Normal file
@@ -0,0 +1,56 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
namespace DateCalculationUnitTests
|
||||
{
|
||||
/** Date Utils **/
|
||||
class DateUtils
|
||||
{
|
||||
public:
|
||||
// Converts SYSTEMTIME structure to DateTime value
|
||||
// Converts: SYSTEMTIME -> FILETIME -> DateTime
|
||||
static Windows::Foundation::DateTime SystemTimeToDateTime(SYSTEMTIME systemTime)
|
||||
{
|
||||
LPFILETIME lpFileTime = new FILETIME();
|
||||
SystemTimeToFileTime(&systemTime, lpFileTime);
|
||||
|
||||
Windows::Foundation::DateTime dateTime;
|
||||
dateTime.UniversalTime = (DWORD)lpFileTime->dwHighDateTime;
|
||||
dateTime.UniversalTime <<= 32;
|
||||
dateTime.UniversalTime |= (DWORD)lpFileTime->dwLowDateTime;
|
||||
|
||||
return dateTime;
|
||||
}
|
||||
|
||||
// Converts DateTime value to SYSTEMTIME structure
|
||||
// Converts: DateTime -> FILETIME -> SYSTEMTIME
|
||||
static SYSTEMTIME DateTimeToSystemTime(Windows::Foundation::DateTime dateTime)
|
||||
{
|
||||
FILETIME fileTime;
|
||||
fileTime.dwLowDateTime = (DWORD)(dateTime.UniversalTime & 0xffffffff);
|
||||
fileTime.dwHighDateTime = (DWORD)(dateTime.UniversalTime >> 32);
|
||||
|
||||
SYSTEMTIME systemTime;
|
||||
FileTimeToSystemTime(&fileTime, &systemTime);
|
||||
|
||||
return systemTime;
|
||||
}
|
||||
|
||||
// Returns long date format for a date
|
||||
static Platform::String^ GetLongDate(SYSTEMTIME systemTime)
|
||||
{
|
||||
auto formatter = ref new Windows::Globalization::DateTimeFormatting::DateTimeFormatter(
|
||||
L"longdate",
|
||||
Windows::Globalization::ApplicationLanguages::Languages,
|
||||
Windows::System::UserProfile::GlobalizationPreferences::HomeGeographicRegion,
|
||||
Windows::Globalization::CalendarIdentifiers::Gregorian,
|
||||
Windows::Globalization::ClockIdentifiers::TwentyFourHour);
|
||||
|
||||
Windows::Foundation::DateTime dateTime = SystemTimeToDateTime(systemTime);
|
||||
return formatter->Format(dateTime);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
31
internal/CalculatorUnitTests/Helpers.h
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#pragma once
|
||||
#include "CalcViewModel\Common\CalculatorButtonUser.h"
|
||||
|
||||
namespace CalculatorUnitTests
|
||||
{
|
||||
#define StandardModePrecision 16
|
||||
#define ScientificModePrecision 32
|
||||
#define ProgrammerModePrecision 64
|
||||
|
||||
typedef struct item
|
||||
{
|
||||
CalculatorApp::NumbersAndOperatorsEnum command;
|
||||
std::wstring expectedPrimaryDisplay;
|
||||
std::wstring expectedExpressions;
|
||||
} TESTITEM;
|
||||
|
||||
namespace UtfUtils {
|
||||
constexpr wchar_t LRE = 0x202a; // Left-to-Right Embedding
|
||||
constexpr wchar_t PDF = 0x202c; // Pop Directional Formatting
|
||||
constexpr wchar_t LRO = 0x202d; // Left-to-Right Override
|
||||
constexpr wchar_t MUL = 0x00d7; // Multiplication Symbol
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
533
internal/CalculatorUnitTests/HistoryTests.cpp
Normal file
@@ -0,0 +1,533 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include <WexTestClass.h>
|
||||
|
||||
#include "CalcViewModel\HistoryViewModel.h"
|
||||
#include "CalcViewModel\StandardCalculatorViewModel.h"
|
||||
|
||||
using namespace CalculationManager;
|
||||
using namespace CalculatorApp;
|
||||
using namespace CalculatorApp::Common;
|
||||
using namespace CalculatorApp::ViewModel;
|
||||
using namespace CalculatorUnitTests;
|
||||
using namespace Platform;
|
||||
using namespace std;
|
||||
using namespace Windows::Storage;
|
||||
using namespace Windows::ApplicationModel::Resources;
|
||||
|
||||
namespace CalculatorFunctionalTests
|
||||
{
|
||||
class HistoryTests
|
||||
{
|
||||
public:
|
||||
TEST_CLASS(HistoryTests);
|
||||
TEST_METHOD(TestHistoryItemClicked);
|
||||
TEST_METHOD(TestHistoryItemAddSingleItem);
|
||||
TEST_METHOD(TestHistoryItemAddMaxItems);
|
||||
TEST_METHOD(TestHistoryClearCommand);
|
||||
TEST_METHOD(TestHistoryClearCommandWithEmptyHistory);
|
||||
TEST_METHOD(TestReLoadHistory);
|
||||
TEST_METHOD(TestSaveAndReloadHistory);
|
||||
TEST_METHOD(TestSerializeDeSerializeHistoryItem);
|
||||
TEST_METHOD(TestHistoryItemWithPrettyExpressions);
|
||||
TEST_METHOD(TestHistoryItemWithPrettyExpressionsMixedRadix);
|
||||
TEST_METHOD(TestHistoryItemLoadAndContinueCalculation);
|
||||
TEST_METHOD(TestDisplayValueAutomationNames);
|
||||
TEST_METHOD(TestRadixAutomationName);
|
||||
TEST_METHOD(TestHistoryEmpty);
|
||||
|
||||
private:
|
||||
HistoryViewModel^ m_historyViewModel;
|
||||
StandardCalculatorViewModel^ m_standardViewModel;
|
||||
|
||||
void Initialize(unsigned int windowId = 0)
|
||||
{
|
||||
m_standardViewModel = ref new StandardCalculatorViewModel();
|
||||
m_standardViewModel->IsStandard = true;
|
||||
m_historyViewModel = ref new HistoryViewModel(m_standardViewModel->m_standardCalculatorManager.get());
|
||||
m_historyViewModel->SetCalculatorDisplay(m_standardViewModel->m_calculatorDisplay);
|
||||
}
|
||||
|
||||
void Cleanup(unsigned int windowId = 0)
|
||||
{
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::ModeBasic);
|
||||
m_historyViewModel->OnClearCommand(nullptr);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::ModeScientific);
|
||||
m_historyViewModel->OnClearCommand(nullptr);
|
||||
m_standardViewModel->m_standardCalculatorManager->Reset();
|
||||
}
|
||||
|
||||
bool IsHistoryContainerEmpty(_In_ String^ historyContainerKey)
|
||||
{
|
||||
ApplicationDataContainer^ localSettings = ApplicationData::Current->LocalSettings;
|
||||
return !(localSettings->Containers->HasKey(historyContainerKey));
|
||||
}
|
||||
|
||||
String^ GetHistoryContainerKeyHelper(CalculationManager::CALCULATOR_MODE cMode)
|
||||
{
|
||||
ValueType^ modeValue = static_cast<int>(cMode);
|
||||
return String::Concat(modeValue->ToString(), L"_History");
|
||||
}
|
||||
|
||||
void MockOnHistoryItemClicked(CalculatorApp::ViewModel::HistoryItemViewModel^ e)
|
||||
{
|
||||
m_standardViewModel->SetHistoryExpressionDisplay(e->GetTokens(), e->GetCommands());
|
||||
m_standardViewModel->SetExpressionDisplay(e->GetTokens(), e->GetCommands());
|
||||
m_standardViewModel->SetPrimaryDisplay(e->Result->Data(), false/*IsError*/);
|
||||
m_standardViewModel->IsFToEEnabled = false;
|
||||
}
|
||||
|
||||
void AddSingleHistoryItem(unsigned int windowId = 0)
|
||||
{
|
||||
Initialize(windowId);
|
||||
int initialSize = m_historyViewModel->ItemSize;
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command1);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandADD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command8);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandEQU);
|
||||
int sizeAfterItemAdd = m_historyViewModel->ItemSize;
|
||||
auto historyItem = m_standardViewModel->m_standardCalculatorManager->GetHistoryItem(0);
|
||||
String^ expression = UtfUtils::LRO + L"1 + 8 =" + UtfUtils::PDF;
|
||||
String ^result = StringReference(L"9");
|
||||
VERIFY_ARE_EQUAL(initialSize + 1, sizeAfterItemAdd);
|
||||
VERIFY_ARE_EQUAL(expression, StringReference(historyItem->historyItemVector.expression.c_str()));
|
||||
VERIFY_ARE_EQUAL(result, StringReference(historyItem->historyItemVector.result.c_str()));
|
||||
Cleanup(windowId);
|
||||
}
|
||||
|
||||
void AddMaxHistoryItems(unsigned int windowId = 0)
|
||||
{
|
||||
Initialize(windowId);
|
||||
int initialSize = m_historyViewModel->ItemSize;
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command1);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandADD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command1);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandEQU);
|
||||
for (int i = 1; i < m_standardViewModel->m_standardCalculatorManager->MaxHistorySize(); i++)
|
||||
{
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command1);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandADD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command2);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandEQU);
|
||||
}
|
||||
VERIFY_ARE_EQUAL(m_historyViewModel->ItemSize, m_standardViewModel->m_standardCalculatorManager->MaxHistorySize());
|
||||
String ^expression = UtfUtils::LRO + L"1 + 1 =" + UtfUtils::PDF;
|
||||
int output = 2;
|
||||
String ^result = output.ToString();
|
||||
auto historyItem = m_standardViewModel->m_standardCalculatorManager->GetHistoryItem(0);
|
||||
VERIFY_ARE_EQUAL(expression, StringReference(historyItem->historyItemVector.expression.c_str()));
|
||||
VERIFY_ARE_EQUAL(result, StringReference(historyItem->historyItemVector.result.c_str()));
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command1);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandADD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command5);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandEQU);
|
||||
VERIFY_ARE_EQUAL(m_historyViewModel->ItemSize, m_standardViewModel->m_standardCalculatorManager->MaxHistorySize());
|
||||
expression = UtfUtils::LRO + L"1 + 2 =" + UtfUtils::PDF;
|
||||
output = 3;
|
||||
result = output.ToString();
|
||||
historyItem = m_standardViewModel->m_standardCalculatorManager->GetHistoryItem(0);
|
||||
VERIFY_ARE_EQUAL(expression, StringReference(historyItem->historyItemVector.expression.c_str()));
|
||||
VERIFY_ARE_EQUAL(result, StringReference(historyItem->historyItemVector.result.c_str()));
|
||||
Cleanup(windowId);
|
||||
}
|
||||
|
||||
void ReloadHistory(unsigned int windowId = 0)
|
||||
{
|
||||
Initialize(windowId);
|
||||
|
||||
m_standardViewModel->m_standardCalculatorManager->Reset();
|
||||
int scientificItems = 5;
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::ModeScientific);
|
||||
for (int i = 0; i < scientificItems; i++)
|
||||
{
|
||||
Command nextCommand = Command(130 + i);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command1);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandADD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(nextCommand);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandEQU);
|
||||
}
|
||||
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::ModeBasic);
|
||||
int standardItems = 2;
|
||||
for (int i = 0; i < standardItems; i++)
|
||||
{
|
||||
Command nextCommand = Command(130 + i);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command1);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandADD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(nextCommand);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandEQU);
|
||||
}
|
||||
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::ModeScientific);
|
||||
m_historyViewModel->ReloadHistory(ViewMode::Scientific);
|
||||
VERIFY_ARE_EQUAL(scientificItems, m_historyViewModel->ItemSize);
|
||||
for (int i = 0; i < scientificItems; i++)
|
||||
{
|
||||
wstring expr = L"1 + " + wstring(i.ToString()->Data()) + L" =";
|
||||
expr = UtfUtils::LRO + expr + UtfUtils::PDF;
|
||||
int output = 1 + i;
|
||||
String ^result = output.ToString();
|
||||
auto historyItem = m_standardViewModel->m_standardCalculatorManager->GetHistoryItem(i);
|
||||
VERIFY_ARE_EQUAL(expr, historyItem->historyItemVector.expression);
|
||||
VERIFY_ARE_EQUAL(result, StringReference(historyItem->historyItemVector.result.c_str()));
|
||||
}
|
||||
|
||||
m_historyViewModel->ReloadHistory(ViewMode::Standard);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::ModeBasic);
|
||||
VERIFY_ARE_EQUAL(standardItems, m_historyViewModel->ItemSize);
|
||||
for (int i = 0; i < standardItems; i++)
|
||||
{
|
||||
wstring expr = L"1 + " + wstring(i.ToString()->Data()) + L" =";
|
||||
expr = UtfUtils::LRO + expr + UtfUtils::PDF;
|
||||
int output = 1 + i;
|
||||
String ^result = output.ToString();
|
||||
auto historyItem = m_standardViewModel->m_standardCalculatorManager->GetHistoryItem(i);
|
||||
VERIFY_ARE_EQUAL(expr, historyItem->historyItemVector.expression);
|
||||
VERIFY_ARE_EQUAL(result, StringReference(historyItem->historyItemVector.result.c_str()));
|
||||
}
|
||||
Cleanup(windowId);
|
||||
}
|
||||
|
||||
void ClearHistory(unsigned int windowId = 0)
|
||||
{
|
||||
Initialize(windowId);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::ModeScientific);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command1);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandADD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command2);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandEQU);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::ModeBasic);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command1);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandADD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command2);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandEQU);
|
||||
m_historyViewModel->OnClearCommand(nullptr);
|
||||
VERIFY_ARE_EQUAL(0, m_historyViewModel->ItemSize);
|
||||
VERIFY_IS_TRUE(IsHistoryContainerEmpty(GetHistoryContainerKeyHelper(CM_STD)));
|
||||
VERIFY_IS_TRUE(IsHistoryContainerEmpty(GetHistoryContainerKeyHelper(CM_SCI)));
|
||||
Cleanup(windowId);
|
||||
}
|
||||
|
||||
void SerializeDeSerializeHistoryItem(unsigned int windowId = 0)
|
||||
{
|
||||
Initialize(windowId);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::ModeScientific);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command1);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandADD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command2);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandEQU);
|
||||
auto itemBeforeSerializeDeserialize = m_standardViewModel->m_standardCalculatorManager->GetHistoryItem(0);
|
||||
m_historyViewModel->SaveHistory();
|
||||
m_historyViewModel->ReloadHistory(ViewMode::Scientific);
|
||||
auto itemAfterSerializeDeserialize = m_standardViewModel->m_standardCalculatorManager->GetHistoryItem(0);
|
||||
VERIFY_IS_TRUE((itemBeforeSerializeDeserialize->historyItemVector.expression == itemAfterSerializeDeserialize->historyItemVector.expression) && (itemBeforeSerializeDeserialize->historyItemVector.result == itemAfterSerializeDeserialize->historyItemVector.result) && (itemBeforeSerializeDeserialize->historyItemVector.spCommands == itemAfterSerializeDeserialize->historyItemVector.spCommands) && (itemBeforeSerializeDeserialize->historyItemVector.spTokens == itemAfterSerializeDeserialize->historyItemVector.spTokens));
|
||||
Cleanup(windowId);
|
||||
}
|
||||
|
||||
void SaveAndReloadHistory(unsigned int windowid = 0)
|
||||
{
|
||||
Initialize(windowid);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::ModeScientific);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command1);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandADD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command8);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandEQU);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command1);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandADD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command2);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandEQU);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::ModeBasic);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command1);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandADD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command6);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandEQU);
|
||||
int itemsBeforeSaveAndReload = m_historyViewModel->ItemSize;
|
||||
m_historyViewModel->SaveHistory();
|
||||
m_historyViewModel->ReloadHistory(ViewMode::Scientific);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::ModeScientific);
|
||||
wstring expr = L"1 + 8 =";
|
||||
// add double quotes around the expression
|
||||
expr = UtfUtils::LRO + expr + UtfUtils::PDF;
|
||||
String ^result = StringReference(L"9");
|
||||
int itemsAfterSaveAndReload = m_historyViewModel->ItemSize;
|
||||
auto historyItem = m_standardViewModel->m_standardCalculatorManager->GetHistoryItem(0);
|
||||
|
||||
VERIFY_ARE_EQUAL(expr, historyItem->historyItemVector.expression);
|
||||
VERIFY_ARE_EQUAL(result, StringReference(historyItem->historyItemVector.result.c_str()));
|
||||
VERIFY_ARE_NOT_EQUAL(itemsBeforeSaveAndReload, itemsAfterSaveAndReload);
|
||||
VERIFY_ARE_EQUAL(itemsBeforeSaveAndReload, itemsAfterSaveAndReload + 1);
|
||||
Cleanup(windowid);
|
||||
}
|
||||
|
||||
void HistoryItemWithPrettyExpressions(unsigned int windowId = 0)
|
||||
{
|
||||
Initialize(windowId);
|
||||
Command commands[] = { Command::CommandSIN, Command::CommandCOS, Command::CommandTAN, Command::CommandASIN, Command::CommandACOS, Command::CommandATAN };
|
||||
Command mode[] = { Command::CommandDEG, Command::CommandRAD, Command::CommandGRAD };
|
||||
int modes = sizeof(mode) / sizeof(Command);
|
||||
int commandsSize = sizeof(commands) / sizeof(Command);
|
||||
ResourceLoader^ m_uiResourceLoader = ResourceLoader::GetForViewIndependentUse(L"CEngineStrings");
|
||||
int itemIndex = 0;
|
||||
int commandResource = 67;
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::ModeScientific);
|
||||
for (int index = 0; index < modes; index++)
|
||||
{
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(mode[index]);
|
||||
for (int command = 0; command < commandsSize; command++)
|
||||
{
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command1);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(commands[command]);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandEQU);
|
||||
auto historyItem = m_standardViewModel->m_standardCalculatorManager->GetHistoryItem(itemIndex);
|
||||
String^ expression = m_uiResourceLoader->GetString(commandResource.ToString());
|
||||
expression += L"( 1 ) =";
|
||||
wstring expr = wstring(expression->Data());
|
||||
expr = UtfUtils::LRO + expr + UtfUtils::PDF;
|
||||
VERIFY_ARE_EQUAL(historyItem->historyItemVector.expression, expr);
|
||||
commandResource++;
|
||||
itemIndex++;
|
||||
}
|
||||
}
|
||||
Cleanup(windowId);
|
||||
}
|
||||
|
||||
void HistoryItemWithPrettyExpressionsMixedRadix(unsigned int windowId = 0)
|
||||
{
|
||||
Initialize(windowId);
|
||||
ResourceLoader^ m_uiResourceLoader = ResourceLoader::GetForViewIndependentUse(L"CEngineStrings");
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::ModeScientific);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandDEG);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command1);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandSIN);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandADD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandRAD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command1);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandSIN);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandADD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandGRAD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command1);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandSIN);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandEQU);
|
||||
auto historyItem = m_standardViewModel->m_standardCalculatorManager->GetHistoryItem(0);
|
||||
String^ expression = m_uiResourceLoader->GetString(L"67");
|
||||
expression += L"( 1 ) + ";
|
||||
expression += m_uiResourceLoader->GetString(L"73");
|
||||
expression += L"( 1 ) + ";
|
||||
expression += m_uiResourceLoader->GetString(L"79");
|
||||
expression += L"( 1 ) =";
|
||||
wstring expr = wstring(expression->Data());
|
||||
expr = UtfUtils::LRO + expr + UtfUtils::PDF;
|
||||
VERIFY_ARE_EQUAL(historyItem->historyItemVector.expression,expr);
|
||||
|
||||
Cleanup(windowId);
|
||||
}
|
||||
|
||||
void HistoryItemClicked(unsigned int windowId = 0)
|
||||
{
|
||||
Initialize(windowId);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::ModeScientific);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command1);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandADD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command5);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandADD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command3);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandEQU);
|
||||
auto historyItem = m_standardViewModel->m_standardCalculatorManager->GetHistoryItem(0);
|
||||
String^ expression = StringReference(historyItem->historyItemVector.expression.c_str());
|
||||
String^ result = StringReference(historyItem->historyItemVector.result.c_str());
|
||||
HistoryItemViewModel ^ item = ref new HistoryItemViewModel(expression, result, historyItem->historyItemVector.spTokens, historyItem->historyItemVector.spCommands);
|
||||
MockOnHistoryItemClicked(item);
|
||||
VERIFY_ARE_EQUAL(StringReference(L"9"), m_standardViewModel->DisplayValue);
|
||||
VERIFY_ARE_EQUAL(StringReference(L"1"), m_standardViewModel->ExpressionTokens->GetAt(0)->Token);
|
||||
VERIFY_ARE_EQUAL(StringReference(L" "), m_standardViewModel->ExpressionTokens->GetAt(1)->Token);
|
||||
VERIFY_ARE_EQUAL(StringReference(L"+"), m_standardViewModel->ExpressionTokens->GetAt(2)->Token);
|
||||
VERIFY_ARE_EQUAL(StringReference(L" "), m_standardViewModel->ExpressionTokens->GetAt(3)->Token);
|
||||
VERIFY_ARE_EQUAL(StringReference(L"5"), m_standardViewModel->ExpressionTokens->GetAt(4)->Token);
|
||||
VERIFY_ARE_EQUAL(StringReference(L" "), m_standardViewModel->ExpressionTokens->GetAt(5)->Token);
|
||||
VERIFY_ARE_EQUAL(StringReference(L"+"), m_standardViewModel->ExpressionTokens->GetAt(6)->Token);
|
||||
VERIFY_ARE_EQUAL(StringReference(L" "), m_standardViewModel->ExpressionTokens->GetAt(7)->Token);
|
||||
Cleanup(windowId);
|
||||
}
|
||||
|
||||
void HistoryItemLoadAndContinueCalculation(unsigned int windowId = 0)
|
||||
{
|
||||
Initialize(windowId);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::ModeBasic);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command1);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandADD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command5);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandADD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command3);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandEQU);
|
||||
|
||||
auto historyItem = m_standardViewModel->m_standardCalculatorManager->GetHistoryItem(0);
|
||||
String^ expression = StringReference(historyItem->historyItemVector.expression.c_str());
|
||||
String^ result = StringReference(historyItem->historyItemVector.result.c_str());
|
||||
HistoryItemViewModel ^ item = ref new HistoryItemViewModel(expression, result, historyItem->historyItemVector.spTokens, historyItem->historyItemVector.spCommands);
|
||||
MockOnHistoryItemClicked(item);
|
||||
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandADD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command5);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandEQU);
|
||||
VERIFY_ARE_EQUAL(StringReference(L"14"), m_standardViewModel->DisplayValue);
|
||||
historyItem = m_standardViewModel->m_standardCalculatorManager->GetHistoryItem(0);
|
||||
expression = StringReference(historyItem->historyItemVector.expression.c_str());
|
||||
result = StringReference(historyItem->historyItemVector.result.c_str());
|
||||
item = ref new HistoryItemViewModel(expression, result, historyItem->historyItemVector.spTokens, historyItem->historyItemVector.spCommands);
|
||||
MockOnHistoryItemClicked(item);
|
||||
VERIFY_ARE_EQUAL(StringReference(L"9"), m_standardViewModel->DisplayValue);
|
||||
|
||||
historyItem = m_standardViewModel->m_standardCalculatorManager->GetHistoryItem(1);
|
||||
expression = StringReference(historyItem->historyItemVector.expression.c_str());
|
||||
result = StringReference(historyItem->historyItemVector.result.c_str());
|
||||
item = ref new HistoryItemViewModel(expression, result, historyItem->historyItemVector.spTokens, historyItem->historyItemVector.spCommands);
|
||||
MockOnHistoryItemClicked(item);
|
||||
VERIFY_ARE_EQUAL(StringReference(L"14"), m_standardViewModel->DisplayValue);
|
||||
Cleanup(windowId);
|
||||
}
|
||||
|
||||
void DisplayValueAutomationNames(unsigned int windowId = 0)
|
||||
{
|
||||
Initialize(windowId);
|
||||
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command1);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandADD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command8);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandEQU);
|
||||
String ^expression = StringReference(L"Display is 9");
|
||||
VERIFY_ARE_EQUAL(expression, m_standardViewModel->CalculationResultAutomationName);
|
||||
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::ModeScientific);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command1);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandADD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command5);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandEQU);
|
||||
expression = StringReference(L"Display is 6");
|
||||
VERIFY_ARE_EQUAL(expression, m_standardViewModel->CalculationResultAutomationName);
|
||||
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::ModeProgrammer);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command1);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandADD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command2);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandEQU);
|
||||
expression = StringReference(L"Display is 3");
|
||||
VERIFY_ARE_EQUAL(expression, m_standardViewModel->CalculationResultAutomationName);
|
||||
|
||||
Cleanup(windowId);
|
||||
}
|
||||
|
||||
void RadixAutomationName(unsigned int windowId = 0)
|
||||
{
|
||||
Initialize(windowId);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::ModeProgrammer);
|
||||
m_standardViewModel->IsProgrammer = true;
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command1);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandADD);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::Command7);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::CommandEQU);
|
||||
String ^expression = L"HexaDecimal" + L" 8";
|
||||
String ^result = L"HexaDecimal " + Utils::GetStringValue(m_standardViewModel->HexDisplayValue);
|
||||
VERIFY_ARE_EQUAL(expression, result);
|
||||
expression = StringReference(L"Octal 10");
|
||||
result = L"Octal " + Utils::GetStringValue(m_standardViewModel->OctalDisplayValue);
|
||||
VERIFY_ARE_EQUAL(expression, result);
|
||||
expression = StringReference(L"Binary 1000");
|
||||
result = L"Binary " + Utils::GetStringValue(m_standardViewModel->BinaryDisplayValue);
|
||||
VERIFY_ARE_EQUAL(expression, result);
|
||||
Cleanup(windowId);
|
||||
}
|
||||
|
||||
void HistoryEmpty(unsigned int windowId = 0)
|
||||
{
|
||||
Initialize(windowId);
|
||||
VERIFY_ARE_EQUAL(0, m_historyViewModel->ItemSize);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::ModeScientific);
|
||||
VERIFY_ARE_EQUAL(0, m_historyViewModel->ItemSize);
|
||||
Cleanup(windowId);
|
||||
}
|
||||
|
||||
void HistoryClearCommandWithEmptyHistory(unsigned int windowId = 0)
|
||||
{
|
||||
Initialize(windowId);
|
||||
VERIFY_ARE_EQUAL(0, m_historyViewModel->ItemSize);
|
||||
m_standardViewModel->m_standardCalculatorManager->SendCommand(Command::ModeScientific);
|
||||
m_historyViewModel->OnClearCommand(nullptr);
|
||||
VERIFY_ARE_EQUAL(0, m_historyViewModel->ItemSize);
|
||||
Cleanup(windowId);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
void HistoryTests::TestHistoryItemAddSingleItem()
|
||||
{
|
||||
AddSingleHistoryItem();
|
||||
}
|
||||
|
||||
void HistoryTests::TestHistoryItemAddMaxItems()
|
||||
{
|
||||
AddMaxHistoryItems();
|
||||
}
|
||||
|
||||
void HistoryTests::TestReLoadHistory()
|
||||
{
|
||||
ReloadHistory();
|
||||
}
|
||||
|
||||
void HistoryTests::TestHistoryClearCommand()
|
||||
{
|
||||
ClearHistory();
|
||||
}
|
||||
|
||||
void HistoryTests::TestSerializeDeSerializeHistoryItem()
|
||||
{
|
||||
SerializeDeSerializeHistoryItem();
|
||||
}
|
||||
|
||||
void HistoryTests::TestSaveAndReloadHistory()
|
||||
{
|
||||
SaveAndReloadHistory();
|
||||
}
|
||||
|
||||
void HistoryTests::TestHistoryItemWithPrettyExpressions()
|
||||
{
|
||||
HistoryItemWithPrettyExpressions();
|
||||
}
|
||||
|
||||
void HistoryTests::TestHistoryItemWithPrettyExpressionsMixedRadix()
|
||||
{
|
||||
HistoryItemWithPrettyExpressionsMixedRadix();
|
||||
}
|
||||
|
||||
void HistoryTests::TestHistoryItemClicked()
|
||||
{
|
||||
HistoryItemClicked();
|
||||
}
|
||||
|
||||
void HistoryTests::TestHistoryItemLoadAndContinueCalculation()
|
||||
{
|
||||
HistoryItemLoadAndContinueCalculation();
|
||||
}
|
||||
|
||||
void HistoryTests::TestDisplayValueAutomationNames()
|
||||
{
|
||||
DisplayValueAutomationNames();
|
||||
}
|
||||
|
||||
void HistoryTests::TestRadixAutomationName()
|
||||
{
|
||||
RadixAutomationName();
|
||||
}
|
||||
|
||||
void HistoryTests::TestHistoryEmpty()
|
||||
{
|
||||
HistoryEmpty();
|
||||
}
|
||||
|
||||
void HistoryTests::TestHistoryClearCommandWithEmptyHistory()
|
||||
{
|
||||
HistoryClearCommandWithEmptyHistory();
|
||||
}
|
||||
}
|
||||
|
56
internal/CalculatorUnitTests/Mocks/CurrencyHttpClient.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pch.h"
|
||||
#include "CurrencyHttpClient.h"
|
||||
|
||||
#include "CalcViewModel\Common\NetworkManager.h"
|
||||
|
||||
using namespace CalculatorApp::DataLoaders;
|
||||
using namespace Platform;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::System::UserProfile;
|
||||
using namespace Windows::Web::Http;
|
||||
|
||||
// Generic responses so unit tests will pass.
|
||||
static constexpr auto STATIC_DATA_RESPONSE = LR"([{"CountryCode":"USA","CountryName":"United States","CurrencyCode":"USD","CurrencyName":"Dollar","CurrencySymbol":"$"},{"CountryCode":"EUR","CountryName":"Europe","CurrencyCode":"EUR","CurrencyName":"Euro","CurrencySymbol":"€"}])";
|
||||
static constexpr auto ALL_RATIOS_RESPONSE = LR"([{"An":"USD","Ch":0,"Pc":0,"Rt":1},{"An":"EUR","Ch":0.003803,"Pc":0.4149,"Rt":0.920503,"Yh":0.9667,"Yl":0.86701}])";
|
||||
|
||||
CurrencyHttpClient::CurrencyHttpClient()
|
||||
{
|
||||
}
|
||||
|
||||
String^ CurrencyHttpClient::GetRawStaticDataResponse()
|
||||
{
|
||||
return StringReference(STATIC_DATA_RESPONSE);
|
||||
}
|
||||
|
||||
String^ CurrencyHttpClient::GetRawAllRatiosDataResponse()
|
||||
{
|
||||
return StringReference(ALL_RATIOS_RESPONSE);
|
||||
}
|
||||
|
||||
IAsyncOperationWithProgress<String^, HttpProgress>^ CurrencyHttpClient::GetCurrencyMetadata()
|
||||
{
|
||||
return ref new MockAsyncOperationWithProgress(StringReference(STATIC_DATA_RESPONSE));
|
||||
}
|
||||
|
||||
IAsyncOperationWithProgress<String^, HttpProgress>^ CurrencyHttpClient::GetCurrencyRatios()
|
||||
{
|
||||
return ref new MockAsyncOperationWithProgress(StringReference(ALL_RATIOS_RESPONSE));
|
||||
}
|
||||
|
||||
MockAsyncOperationWithProgress::MockAsyncOperationWithProgress(String^ result) :
|
||||
m_result(result)
|
||||
{
|
||||
}
|
||||
|
||||
HResult MockAsyncOperationWithProgress::ErrorCode::get()
|
||||
{
|
||||
HResult okayResult;
|
||||
okayResult.Value = S_OK;
|
||||
return okayResult;
|
||||
}
|
||||
|
75
internal/CalculatorUnitTests/Mocks/CurrencyHttpClient.h
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CalcViewModel\DataLoaders\ICurrencyHttpClient.h"
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace DataLoaders
|
||||
{
|
||||
class CurrencyHttpClient : public ICurrencyHttpClient
|
||||
{
|
||||
public:
|
||||
CurrencyHttpClient();
|
||||
|
||||
static Platform::String^ GetRawStaticDataResponse();
|
||||
static Platform::String^ GetRawAllRatiosDataResponse();
|
||||
|
||||
// ICurrencyHttpClient
|
||||
void SetSourceCurrencyCode(Platform::String^ sourceCurrencyCode) override {}
|
||||
void SetResponseLanguage(Platform::String^ responseLanguage) override {}
|
||||
|
||||
virtual Windows::Foundation::IAsyncOperationWithProgress<Platform::String^, Windows::Web::Http::HttpProgress>^ GetCurrencyMetadata() override;
|
||||
virtual Windows::Foundation::IAsyncOperationWithProgress<Platform::String^, Windows::Web::Http::HttpProgress>^ GetCurrencyRatios() override;
|
||||
// ICurrencyHttpClient
|
||||
};
|
||||
|
||||
public ref class MockAsyncOperationWithProgress sealed :
|
||||
public Windows::Foundation::IAsyncOperationWithProgress<Platform::String^, Windows::Web::Http::HttpProgress>
|
||||
{
|
||||
public:
|
||||
MockAsyncOperationWithProgress(Platform::String^ result);
|
||||
|
||||
// IAsyncInfo
|
||||
virtual property Windows::Foundation::HResult ErrorCode
|
||||
{
|
||||
Windows::Foundation::HResult get();
|
||||
}
|
||||
|
||||
virtual property unsigned int Id
|
||||
{
|
||||
unsigned int get() { return 128u; }
|
||||
}
|
||||
|
||||
virtual property Windows::Foundation::AsyncStatus Status
|
||||
{
|
||||
Windows::Foundation::AsyncStatus get() { return Windows::Foundation::AsyncStatus::Completed; }
|
||||
}
|
||||
|
||||
virtual void Cancel() {}
|
||||
virtual void Close() {}
|
||||
// IAsyncInfo
|
||||
|
||||
// IAsyncOperationWithProgress
|
||||
virtual property Windows::Foundation::AsyncOperationProgressHandler<Platform::String^, Windows::Web::Http::HttpProgress>^ Progress
|
||||
{
|
||||
Windows::Foundation::AsyncOperationProgressHandler<Platform::String^, Windows::Web::Http::HttpProgress>^ get() { return nullptr; }
|
||||
void set(Windows::Foundation::AsyncOperationProgressHandler<Platform::String^, Windows::Web::Http::HttpProgress>^ handler) {}
|
||||
}
|
||||
|
||||
virtual property Windows::Foundation::AsyncOperationWithProgressCompletedHandler<Platform::String^, Windows::Web::Http::HttpProgress>^ Completed
|
||||
{
|
||||
Windows::Foundation::AsyncOperationWithProgressCompletedHandler<Platform::String^, Windows::Web::Http::HttpProgress>^ get() { return nullptr; }
|
||||
void set(Windows::Foundation::AsyncOperationWithProgressCompletedHandler<Platform::String^, Windows::Web::Http::HttpProgress>^ handler) {}
|
||||
}
|
||||
|
||||
virtual Platform::String^ GetResults() { return m_result; }
|
||||
// IAsyncOperationWithProgress
|
||||
|
||||
private:
|
||||
Platform::String^ m_result;
|
||||
};
|
||||
}
|
||||
}
|
22
internal/CalculatorUnitTests/Module.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include <WexTestClass.h>
|
||||
|
||||
namespace CalculatorUnitTests
|
||||
{
|
||||
BEGIN_MODULE()
|
||||
MODULE_PROPERTY(L"APPX:CertificateFileName", L"CalculatorUnitTests.cer:TrustedPeople")
|
||||
END_MODULE()
|
||||
|
||||
MODULE_SETUP(ModuleSetup)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
MODULE_CLEANUP(ModuleCleanup)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
1012
internal/CalculatorUnitTests/MultiWindowUnitTests.cpp
Normal file
410
internal/CalculatorUnitTests/NavCategoryUnitTests.cpp
Normal file
@@ -0,0 +1,410 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include <WexTestClass.h>
|
||||
|
||||
using namespace CalculatorApp::Common;
|
||||
using namespace CalculatorUnitTests;
|
||||
using namespace Platform;
|
||||
using namespace std;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
|
||||
namespace CalculatorUnitTests
|
||||
{
|
||||
class NavCategoryUnitTests
|
||||
{
|
||||
public:
|
||||
TEST_CLASS(NavCategoryUnitTests);
|
||||
|
||||
TEST_METHOD(Serialize);
|
||||
TEST_METHOD(Deserialize_AllValid);
|
||||
TEST_METHOD(Deserialize_AllInvalid);
|
||||
|
||||
TEST_METHOD(IsValidViewMode_AllValid);
|
||||
TEST_METHOD(IsValidViewMode_AllInvalid);
|
||||
|
||||
TEST_METHOD(IsCalculatorViewMode);
|
||||
TEST_METHOD(IsDateCalculatorViewMode);
|
||||
TEST_METHOD(IsConverterViewMode);
|
||||
|
||||
TEST_METHOD(GetFriendlyName);
|
||||
TEST_METHOD(GetGroupType);
|
||||
TEST_METHOD(GetIndex);
|
||||
TEST_METHOD(GetPosition);
|
||||
TEST_METHOD(GetIndex_GetPosition_Relationship);
|
||||
TEST_METHOD(GetIndexInGroup);
|
||||
|
||||
TEST_METHOD(GetViewModeForVirtualKey);
|
||||
};
|
||||
|
||||
void NavCategoryUnitTests::Serialize()
|
||||
{
|
||||
// While values in other tests may change (for example, the order
|
||||
// of a navigation item might change), these values should NEVER
|
||||
// change. We are validating the unique ID for each mode, not
|
||||
// it's position or index.
|
||||
VERIFY_ARE_EQUAL(0, NavCategory::Serialize(ViewMode::Standard));
|
||||
VERIFY_ARE_EQUAL(1, NavCategory::Serialize(ViewMode::Scientific));
|
||||
VERIFY_ARE_EQUAL(2, NavCategory::Serialize(ViewMode::Programmer));
|
||||
VERIFY_ARE_EQUAL(3, NavCategory::Serialize(ViewMode::Date));
|
||||
VERIFY_ARE_EQUAL(16, NavCategory::Serialize(ViewMode::Currency));
|
||||
VERIFY_ARE_EQUAL(4, NavCategory::Serialize(ViewMode::Volume));
|
||||
VERIFY_ARE_EQUAL(5, NavCategory::Serialize(ViewMode::Length));
|
||||
VERIFY_ARE_EQUAL(6, NavCategory::Serialize(ViewMode::Weight));
|
||||
VERIFY_ARE_EQUAL(7, NavCategory::Serialize(ViewMode::Temperature));
|
||||
VERIFY_ARE_EQUAL(8, NavCategory::Serialize(ViewMode::Energy));
|
||||
VERIFY_ARE_EQUAL(9, NavCategory::Serialize(ViewMode::Area));
|
||||
VERIFY_ARE_EQUAL(10, NavCategory::Serialize(ViewMode::Speed));
|
||||
VERIFY_ARE_EQUAL(11, NavCategory::Serialize(ViewMode::Time));
|
||||
VERIFY_ARE_EQUAL(12, NavCategory::Serialize(ViewMode::Power));
|
||||
VERIFY_ARE_EQUAL(13, NavCategory::Serialize(ViewMode::Data));
|
||||
VERIFY_ARE_EQUAL(14, NavCategory::Serialize(ViewMode::Pressure));
|
||||
VERIFY_ARE_EQUAL(15, NavCategory::Serialize(ViewMode::Angle));
|
||||
|
||||
VERIFY_ARE_EQUAL(-1, NavCategory::Serialize(ViewMode::None));
|
||||
}
|
||||
|
||||
void NavCategoryUnitTests::Deserialize_AllValid()
|
||||
{
|
||||
// While values in other tests may change (for example, the order
|
||||
// of a navigation item might change), these values should NEVER
|
||||
// change. We are validating the unique ID for each mode, not
|
||||
// it's position or index.
|
||||
VERIFY_ARE_EQUAL(ViewMode::Standard, NavCategory::Deserialize(ref new Box<int>(0)));
|
||||
VERIFY_ARE_EQUAL(ViewMode::Scientific, NavCategory::Deserialize(ref new Box<int>(1)));
|
||||
VERIFY_ARE_EQUAL(ViewMode::Programmer, NavCategory::Deserialize(ref new Box<int>(2)));
|
||||
VERIFY_ARE_EQUAL(ViewMode::Date, NavCategory::Deserialize(ref new Box<int>(3)));
|
||||
VERIFY_ARE_EQUAL(ViewMode::Currency, NavCategory::Deserialize(ref new Box<int>(16)));
|
||||
VERIFY_ARE_EQUAL(ViewMode::Volume, NavCategory::Deserialize(ref new Box<int>(4)));
|
||||
VERIFY_ARE_EQUAL(ViewMode::Length, NavCategory::Deserialize(ref new Box<int>(5)));
|
||||
VERIFY_ARE_EQUAL(ViewMode::Weight, NavCategory::Deserialize(ref new Box<int>(6)));
|
||||
VERIFY_ARE_EQUAL(ViewMode::Temperature, NavCategory::Deserialize(ref new Box<int>(7)));
|
||||
VERIFY_ARE_EQUAL(ViewMode::Energy, NavCategory::Deserialize(ref new Box<int>(8)));
|
||||
VERIFY_ARE_EQUAL(ViewMode::Area, NavCategory::Deserialize(ref new Box<int>(9)));
|
||||
VERIFY_ARE_EQUAL(ViewMode::Speed, NavCategory::Deserialize(ref new Box<int>(10)));
|
||||
VERIFY_ARE_EQUAL(ViewMode::Time, NavCategory::Deserialize(ref new Box<int>(11)));
|
||||
VERIFY_ARE_EQUAL(ViewMode::Power, NavCategory::Deserialize(ref new Box<int>(12)));
|
||||
VERIFY_ARE_EQUAL(ViewMode::Data, NavCategory::Deserialize(ref new Box<int>(13)));
|
||||
VERIFY_ARE_EQUAL(ViewMode::Pressure, NavCategory::Deserialize(ref new Box<int>(14)));
|
||||
VERIFY_ARE_EQUAL(ViewMode::Angle, NavCategory::Deserialize(ref new Box<int>(15)));
|
||||
}
|
||||
|
||||
void NavCategoryUnitTests::Deserialize_AllInvalid()
|
||||
{
|
||||
VERIFY_ARE_EQUAL(ViewMode::None, NavCategory::Deserialize(nullptr));
|
||||
VERIFY_ARE_EQUAL(ViewMode::None, NavCategory::Deserialize(ref new String(L"fail")));
|
||||
|
||||
// Boundary testing
|
||||
VERIFY_ARE_EQUAL(ViewMode::None, NavCategory::Deserialize(ref new Box<int>(-1)));
|
||||
VERIFY_ARE_EQUAL(ViewMode::None, NavCategory::Deserialize(ref new Box<int>(17)));
|
||||
}
|
||||
|
||||
void NavCategoryUnitTests::IsValidViewMode_AllValid()
|
||||
{
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(ViewMode::Standard));
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(ViewMode::Scientific));
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(ViewMode::Programmer));
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(ViewMode::Date));
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(ViewMode::Currency));
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(ViewMode::Volume));
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(ViewMode::Length));
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(ViewMode::Weight));
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(ViewMode::Temperature));
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(ViewMode::Energy));
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(ViewMode::Area));
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(ViewMode::Speed));
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(ViewMode::Time));
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(ViewMode::Power));
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(ViewMode::Data));
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(ViewMode::Pressure));
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(ViewMode::Angle));
|
||||
}
|
||||
|
||||
void NavCategoryUnitTests::IsValidViewMode_AllInvalid()
|
||||
{
|
||||
VERIFY_IS_FALSE(NavCategory::IsValidViewMode(ViewMode::None));
|
||||
|
||||
// There are 17 total options so int 17 should be the first invalid
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(static_cast<ViewMode>(16)));
|
||||
VERIFY_IS_FALSE(NavCategory::IsValidViewMode(static_cast<ViewMode>(17)));
|
||||
|
||||
// Also verify the lower bound
|
||||
VERIFY_IS_TRUE(NavCategory::IsValidViewMode(static_cast<ViewMode>(0)));
|
||||
VERIFY_IS_FALSE(NavCategory::IsValidViewMode(static_cast<ViewMode>(-1)));
|
||||
}
|
||||
|
||||
void NavCategoryUnitTests::IsCalculatorViewMode()
|
||||
{
|
||||
VERIFY_IS_TRUE(NavCategory::IsCalculatorViewMode(ViewMode::Standard));
|
||||
VERIFY_IS_TRUE(NavCategory::IsCalculatorViewMode(ViewMode::Scientific));
|
||||
VERIFY_IS_TRUE(NavCategory::IsCalculatorViewMode(ViewMode::Programmer));
|
||||
|
||||
VERIFY_IS_FALSE(NavCategory::IsCalculatorViewMode(ViewMode::Date));
|
||||
|
||||
VERIFY_IS_FALSE(NavCategory::IsCalculatorViewMode(ViewMode::Currency));
|
||||
VERIFY_IS_FALSE(NavCategory::IsCalculatorViewMode(ViewMode::Volume));
|
||||
VERIFY_IS_FALSE(NavCategory::IsCalculatorViewMode(ViewMode::Length));
|
||||
VERIFY_IS_FALSE(NavCategory::IsCalculatorViewMode(ViewMode::Weight));
|
||||
VERIFY_IS_FALSE(NavCategory::IsCalculatorViewMode(ViewMode::Temperature));
|
||||
VERIFY_IS_FALSE(NavCategory::IsCalculatorViewMode(ViewMode::Energy));
|
||||
VERIFY_IS_FALSE(NavCategory::IsCalculatorViewMode(ViewMode::Area));
|
||||
VERIFY_IS_FALSE(NavCategory::IsCalculatorViewMode(ViewMode::Speed));
|
||||
VERIFY_IS_FALSE(NavCategory::IsCalculatorViewMode(ViewMode::Time));
|
||||
VERIFY_IS_FALSE(NavCategory::IsCalculatorViewMode(ViewMode::Power));
|
||||
VERIFY_IS_FALSE(NavCategory::IsCalculatorViewMode(ViewMode::Data));
|
||||
VERIFY_IS_FALSE(NavCategory::IsCalculatorViewMode(ViewMode::Pressure));
|
||||
VERIFY_IS_FALSE(NavCategory::IsCalculatorViewMode(ViewMode::Angle));
|
||||
}
|
||||
|
||||
void NavCategoryUnitTests::IsDateCalculatorViewMode()
|
||||
{
|
||||
VERIFY_IS_FALSE(NavCategory::IsDateCalculatorViewMode(ViewMode::Standard));
|
||||
VERIFY_IS_FALSE(NavCategory::IsDateCalculatorViewMode(ViewMode::Scientific));
|
||||
VERIFY_IS_FALSE(NavCategory::IsDateCalculatorViewMode(ViewMode::Programmer));
|
||||
|
||||
VERIFY_IS_TRUE(NavCategory::IsDateCalculatorViewMode(ViewMode::Date));
|
||||
|
||||
VERIFY_IS_FALSE(NavCategory::IsDateCalculatorViewMode(ViewMode::Currency));
|
||||
VERIFY_IS_FALSE(NavCategory::IsDateCalculatorViewMode(ViewMode::Volume));
|
||||
VERIFY_IS_FALSE(NavCategory::IsDateCalculatorViewMode(ViewMode::Length));
|
||||
VERIFY_IS_FALSE(NavCategory::IsDateCalculatorViewMode(ViewMode::Weight));
|
||||
VERIFY_IS_FALSE(NavCategory::IsDateCalculatorViewMode(ViewMode::Temperature));
|
||||
VERIFY_IS_FALSE(NavCategory::IsDateCalculatorViewMode(ViewMode::Energy));
|
||||
VERIFY_IS_FALSE(NavCategory::IsDateCalculatorViewMode(ViewMode::Area));
|
||||
VERIFY_IS_FALSE(NavCategory::IsDateCalculatorViewMode(ViewMode::Speed));
|
||||
VERIFY_IS_FALSE(NavCategory::IsDateCalculatorViewMode(ViewMode::Time));
|
||||
VERIFY_IS_FALSE(NavCategory::IsDateCalculatorViewMode(ViewMode::Power));
|
||||
VERIFY_IS_FALSE(NavCategory::IsDateCalculatorViewMode(ViewMode::Data));
|
||||
VERIFY_IS_FALSE(NavCategory::IsDateCalculatorViewMode(ViewMode::Pressure));
|
||||
VERIFY_IS_FALSE(NavCategory::IsDateCalculatorViewMode(ViewMode::Angle));
|
||||
}
|
||||
|
||||
void NavCategoryUnitTests::IsConverterViewMode()
|
||||
{
|
||||
VERIFY_IS_FALSE(NavCategory::IsConverterViewMode(ViewMode::Standard));
|
||||
VERIFY_IS_FALSE(NavCategory::IsConverterViewMode(ViewMode::Scientific));
|
||||
VERIFY_IS_FALSE(NavCategory::IsConverterViewMode(ViewMode::Programmer));
|
||||
|
||||
VERIFY_IS_FALSE(NavCategory::IsConverterViewMode(ViewMode::Date));
|
||||
|
||||
VERIFY_IS_TRUE(NavCategory::IsConverterViewMode(ViewMode::Currency));
|
||||
VERIFY_IS_TRUE(NavCategory::IsConverterViewMode(ViewMode::Volume));
|
||||
VERIFY_IS_TRUE(NavCategory::IsConverterViewMode(ViewMode::Length));
|
||||
VERIFY_IS_TRUE(NavCategory::IsConverterViewMode(ViewMode::Weight));
|
||||
VERIFY_IS_TRUE(NavCategory::IsConverterViewMode(ViewMode::Temperature));
|
||||
VERIFY_IS_TRUE(NavCategory::IsConverterViewMode(ViewMode::Energy));
|
||||
VERIFY_IS_TRUE(NavCategory::IsConverterViewMode(ViewMode::Area));
|
||||
VERIFY_IS_TRUE(NavCategory::IsConverterViewMode(ViewMode::Speed));
|
||||
VERIFY_IS_TRUE(NavCategory::IsConverterViewMode(ViewMode::Time));
|
||||
VERIFY_IS_TRUE(NavCategory::IsConverterViewMode(ViewMode::Power));
|
||||
VERIFY_IS_TRUE(NavCategory::IsConverterViewMode(ViewMode::Data));
|
||||
VERIFY_IS_TRUE(NavCategory::IsConverterViewMode(ViewMode::Pressure));
|
||||
VERIFY_IS_TRUE(NavCategory::IsConverterViewMode(ViewMode::Angle));
|
||||
}
|
||||
|
||||
void NavCategoryUnitTests::GetFriendlyName()
|
||||
{
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Standard"), NavCategory::GetFriendlyName(ViewMode::Standard));
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Scientific"), NavCategory::GetFriendlyName(ViewMode::Scientific));
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Programmer"), NavCategory::GetFriendlyName(ViewMode::Programmer));
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Date"), NavCategory::GetFriendlyName(ViewMode::Date));
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Currency"), NavCategory::GetFriendlyName(ViewMode::Currency));
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Volume"), NavCategory::GetFriendlyName(ViewMode::Volume));
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Length"), NavCategory::GetFriendlyName(ViewMode::Length));
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Weight and Mass"), NavCategory::GetFriendlyName(ViewMode::Weight));
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Temperature"), NavCategory::GetFriendlyName(ViewMode::Temperature));
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Energy"), NavCategory::GetFriendlyName(ViewMode::Energy));
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Area"), NavCategory::GetFriendlyName(ViewMode::Area));
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Speed"), NavCategory::GetFriendlyName(ViewMode::Speed));
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Time"), NavCategory::GetFriendlyName(ViewMode::Time));
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Power"), NavCategory::GetFriendlyName(ViewMode::Power));
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Data"), NavCategory::GetFriendlyName(ViewMode::Data));
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Pressure"), NavCategory::GetFriendlyName(ViewMode::Pressure));
|
||||
VERIFY_ARE_EQUAL(StringReference(L"Angle"), NavCategory::GetFriendlyName(ViewMode::Angle));
|
||||
|
||||
VERIFY_ARE_EQUAL(StringReference(L"None"), NavCategory::GetFriendlyName(ViewMode::None));
|
||||
}
|
||||
|
||||
void NavCategoryUnitTests::GetGroupType()
|
||||
{
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Calculator, NavCategory::GetGroupType(ViewMode::Standard));
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Calculator, NavCategory::GetGroupType(ViewMode::Scientific));
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Calculator, NavCategory::GetGroupType(ViewMode::Programmer));
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Calculator, NavCategory::GetGroupType(ViewMode::Date));
|
||||
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Converter, NavCategory::GetGroupType(ViewMode::Currency));
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Converter, NavCategory::GetGroupType(ViewMode::Volume));
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Converter, NavCategory::GetGroupType(ViewMode::Length));
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Converter, NavCategory::GetGroupType(ViewMode::Weight));
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Converter, NavCategory::GetGroupType(ViewMode::Temperature));
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Converter, NavCategory::GetGroupType(ViewMode::Energy));
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Converter, NavCategory::GetGroupType(ViewMode::Area));
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Converter, NavCategory::GetGroupType(ViewMode::Speed));
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Converter, NavCategory::GetGroupType(ViewMode::Time));
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Converter, NavCategory::GetGroupType(ViewMode::Power));
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Converter, NavCategory::GetGroupType(ViewMode::Data));
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Converter, NavCategory::GetGroupType(ViewMode::Pressure));
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Converter, NavCategory::GetGroupType(ViewMode::Angle));
|
||||
}
|
||||
|
||||
void NavCategoryUnitTests::GetIndex()
|
||||
{
|
||||
// Index is the 0-based ordering of modes
|
||||
vector<ViewMode> orderedModes = {
|
||||
ViewMode::Standard,
|
||||
ViewMode::Scientific,
|
||||
ViewMode::Programmer,
|
||||
ViewMode::Date,
|
||||
ViewMode::Currency,
|
||||
ViewMode::Volume,
|
||||
ViewMode::Length,
|
||||
ViewMode::Weight,
|
||||
ViewMode::Temperature,
|
||||
ViewMode::Energy,
|
||||
ViewMode::Area,
|
||||
ViewMode::Speed,
|
||||
ViewMode::Time,
|
||||
ViewMode::Power,
|
||||
ViewMode::Data,
|
||||
ViewMode::Pressure,
|
||||
ViewMode::Angle
|
||||
};
|
||||
|
||||
for (size_t index = 0; index < orderedModes.size(); index++)
|
||||
{
|
||||
ViewMode mode = orderedModes[index];
|
||||
VERIFY_ARE_EQUAL(index, NavCategory::GetIndex(mode));
|
||||
}
|
||||
|
||||
VERIFY_ARE_EQUAL(-1, NavCategory::GetIndex(ViewMode::None));
|
||||
}
|
||||
|
||||
void NavCategoryUnitTests::GetPosition()
|
||||
{
|
||||
// Position is the 1-based ordering of modes
|
||||
vector<ViewMode> orderedModes = {
|
||||
ViewMode::Standard,
|
||||
ViewMode::Scientific,
|
||||
ViewMode::Programmer,
|
||||
ViewMode::Date,
|
||||
ViewMode::Currency,
|
||||
ViewMode::Volume,
|
||||
ViewMode::Length,
|
||||
ViewMode::Weight,
|
||||
ViewMode::Temperature,
|
||||
ViewMode::Energy,
|
||||
ViewMode::Area,
|
||||
ViewMode::Speed,
|
||||
ViewMode::Time,
|
||||
ViewMode::Power,
|
||||
ViewMode::Data,
|
||||
ViewMode::Pressure,
|
||||
ViewMode::Angle
|
||||
};
|
||||
|
||||
for (size_t pos = 1; pos <= orderedModes.size(); pos++)
|
||||
{
|
||||
ViewMode mode = orderedModes[pos - 1];
|
||||
VERIFY_ARE_EQUAL(pos, NavCategory::GetPosition(mode));
|
||||
}
|
||||
|
||||
VERIFY_ARE_EQUAL(-1, NavCategory::GetPosition(ViewMode::None));
|
||||
}
|
||||
|
||||
void NavCategoryUnitTests::GetIndex_GetPosition_Relationship()
|
||||
{
|
||||
// Index should be 1 less than Position.
|
||||
// The other checks verify the order of Index and Position.
|
||||
// Just verify the relationship here.
|
||||
VERIFY_ARE_EQUAL(NavCategory::GetIndex(ViewMode::Standard) + 1, NavCategory::GetPosition(ViewMode::Standard));
|
||||
VERIFY_ARE_EQUAL(NavCategory::GetPosition(ViewMode::Volume) - 1, NavCategory::GetIndex(ViewMode::Volume));
|
||||
}
|
||||
|
||||
void NavCategoryUnitTests::GetIndexInGroup()
|
||||
{
|
||||
VERIFY_ARE_EQUAL(0, NavCategory::GetIndexInGroup(ViewMode::Standard, CategoryGroupType::Calculator));
|
||||
VERIFY_ARE_EQUAL(1, NavCategory::GetIndexInGroup(ViewMode::Scientific, CategoryGroupType::Calculator));
|
||||
VERIFY_ARE_EQUAL(2, NavCategory::GetIndexInGroup(ViewMode::Programmer, CategoryGroupType::Calculator));
|
||||
VERIFY_ARE_EQUAL(3, NavCategory::GetIndexInGroup(ViewMode::Date, CategoryGroupType::Calculator));
|
||||
|
||||
VERIFY_ARE_EQUAL(0, NavCategory::GetIndexInGroup(ViewMode::Currency, CategoryGroupType::Converter));
|
||||
VERIFY_ARE_EQUAL(1, NavCategory::GetIndexInGroup(ViewMode::Volume, CategoryGroupType::Converter));
|
||||
VERIFY_ARE_EQUAL(2, NavCategory::GetIndexInGroup(ViewMode::Length, CategoryGroupType::Converter));
|
||||
VERIFY_ARE_EQUAL(3, NavCategory::GetIndexInGroup(ViewMode::Weight, CategoryGroupType::Converter));
|
||||
VERIFY_ARE_EQUAL(4, NavCategory::GetIndexInGroup(ViewMode::Temperature, CategoryGroupType::Converter));
|
||||
VERIFY_ARE_EQUAL(5, NavCategory::GetIndexInGroup(ViewMode::Energy, CategoryGroupType::Converter));
|
||||
VERIFY_ARE_EQUAL(6, NavCategory::GetIndexInGroup(ViewMode::Area, CategoryGroupType::Converter));
|
||||
VERIFY_ARE_EQUAL(7, NavCategory::GetIndexInGroup(ViewMode::Speed, CategoryGroupType::Converter));
|
||||
VERIFY_ARE_EQUAL(8, NavCategory::GetIndexInGroup(ViewMode::Time, CategoryGroupType::Converter));
|
||||
VERIFY_ARE_EQUAL(9, NavCategory::GetIndexInGroup(ViewMode::Power, CategoryGroupType::Converter));
|
||||
VERIFY_ARE_EQUAL(10, NavCategory::GetIndexInGroup(ViewMode::Data, CategoryGroupType::Converter));
|
||||
VERIFY_ARE_EQUAL(11, NavCategory::GetIndexInGroup(ViewMode::Pressure, CategoryGroupType::Converter));
|
||||
VERIFY_ARE_EQUAL(12, NavCategory::GetIndexInGroup(ViewMode::Angle, CategoryGroupType::Converter));
|
||||
|
||||
VERIFY_ARE_EQUAL(-1, NavCategory::GetIndexInGroup(ViewMode::None, CategoryGroupType::Calculator));
|
||||
VERIFY_ARE_EQUAL(-1, NavCategory::GetIndexInGroup(ViewMode::None, CategoryGroupType::Converter));
|
||||
}
|
||||
|
||||
void NavCategoryUnitTests::GetViewModeForVirtualKey()
|
||||
{
|
||||
VERIFY_ARE_EQUAL(ViewMode::Standard, NavCategory::GetViewModeForVirtualKey(MyVirtualKey::Number1));
|
||||
VERIFY_ARE_EQUAL(ViewMode::Scientific, NavCategory::GetViewModeForVirtualKey(MyVirtualKey::Number2));
|
||||
VERIFY_ARE_EQUAL(ViewMode::Programmer, NavCategory::GetViewModeForVirtualKey(MyVirtualKey::Number3));
|
||||
}
|
||||
|
||||
class NavCategoryGroupUnitTests
|
||||
{
|
||||
public:
|
||||
TEST_CLASS(NavCategoryGroupUnitTests);
|
||||
|
||||
TEST_METHOD(CreateNavCategoryGroup);
|
||||
|
||||
private:
|
||||
void ValidateNavCategory(IObservableVector<NavCategory^>^ categories, unsigned int index, ViewMode expectedMode, int expectedPosition)
|
||||
{
|
||||
VERIFY_IS_LESS_THAN(0u, categories->Size);
|
||||
VERIFY_IS_GREATER_THAN(categories->Size, index);
|
||||
|
||||
NavCategory^ category = categories->GetAt(index);
|
||||
VERIFY_ARE_EQUAL(expectedMode, category->Mode);
|
||||
VERIFY_ARE_EQUAL(expectedPosition, category->Position);
|
||||
}
|
||||
};
|
||||
|
||||
void NavCategoryGroupUnitTests::CreateNavCategoryGroup()
|
||||
{
|
||||
IObservableVector<NavCategoryGroup^>^ menuOptions = NavCategoryGroup::CreateMenuOptions();
|
||||
|
||||
VERIFY_ARE_EQUAL(2, menuOptions->Size);
|
||||
|
||||
NavCategoryGroup^ calculatorGroup = menuOptions->GetAt(0);
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Calculator, calculatorGroup->GroupType);
|
||||
|
||||
IObservableVector<NavCategory^>^ calculatorCategories = calculatorGroup->Categories;
|
||||
VERIFY_ARE_EQUAL(4, calculatorCategories->Size);
|
||||
ValidateNavCategory(calculatorCategories, 0u, ViewMode::Standard, 1);
|
||||
ValidateNavCategory(calculatorCategories, 1u, ViewMode::Scientific, 2);
|
||||
ValidateNavCategory(calculatorCategories, 2u, ViewMode::Programmer, 3);
|
||||
ValidateNavCategory(calculatorCategories, 3u, ViewMode::Date, 4);
|
||||
|
||||
NavCategoryGroup^ converterGroup = menuOptions->GetAt(1);
|
||||
VERIFY_ARE_EQUAL(CategoryGroupType::Converter, converterGroup->GroupType);
|
||||
|
||||
IObservableVector<NavCategory^>^ converterCategories = converterGroup->Categories;
|
||||
VERIFY_ARE_EQUAL(13, converterCategories->Size);
|
||||
ValidateNavCategory(converterCategories, 0u, ViewMode::Currency, 5);
|
||||
ValidateNavCategory(converterCategories, 1u, ViewMode::Volume, 6);
|
||||
ValidateNavCategory(converterCategories, 2u, ViewMode::Length, 7);
|
||||
ValidateNavCategory(converterCategories, 3u, ViewMode::Weight, 8);
|
||||
ValidateNavCategory(converterCategories, 4u, ViewMode::Temperature, 9);
|
||||
ValidateNavCategory(converterCategories, 5u, ViewMode::Energy, 10);
|
||||
ValidateNavCategory(converterCategories, 6u, ViewMode::Area, 11);
|
||||
ValidateNavCategory(converterCategories, 7u, ViewMode::Speed, 12);
|
||||
ValidateNavCategory(converterCategories, 8u, ViewMode::Time, 13);
|
||||
ValidateNavCategory(converterCategories, 9u, ViewMode::Power, 14);
|
||||
ValidateNavCategory(converterCategories, 10u, ViewMode::Data, 15);
|
||||
ValidateNavCategory(converterCategories, 11u, ViewMode::Pressure, 16);
|
||||
ValidateNavCategory(converterCategories, 12u, ViewMode::Angle, 17);
|
||||
}
|
||||
}
|
29
internal/CalculatorUnitTests/Package.appxmanifest
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp">
|
||||
<Identity Name="bb12762c-62f1-4063-95c9-170805a2cb5b" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" Version="1.0.0.0" />
|
||||
<mp:PhoneIdentity PhoneProductId="bb12762c-62f1-4063-95c9-170805a2cb5b" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||
<Properties>
|
||||
<DisplayName>CalculatorUnitTests</DisplayName>
|
||||
<PublisherDisplayName>Microsoft Corporation</PublisherDisplayName>
|
||||
<Logo>Assets\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
|
||||
</Dependencies>
|
||||
<Resources>
|
||||
<Resource Language="x-generate" />
|
||||
</Resources>
|
||||
<Applications>
|
||||
<Application Id="taef.executionengine.universal.App" Executable="$targetnametoken$.exe" EntryPoint="CalculatorUnitTests.App">
|
||||
<uap:VisualElements DisplayName="CalculatorUnitTests" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="CalculatorUnitTests" BackgroundColor="transparent">
|
||||
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png">
|
||||
</uap:DefaultTile>
|
||||
<uap:SplashScreen Image="Assets\SplashScreen.png" />
|
||||
</uap:VisualElements>
|
||||
</Application>
|
||||
</Applications>
|
||||
<Capabilities>
|
||||
<Capability Name="internetClient" />
|
||||
<Capability Name="internetClientServer" />
|
||||
</Capabilities>
|
||||
</Package>
|
1144
internal/CalculatorUnitTests/StandardViewModelUnitTests.cpp
Normal file
440
internal/CalculatorUnitTests/Test.resw
Normal file
@@ -0,0 +1,440 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Square meters-Acres">
|
||||
<value>4046.8564224</value></data>
|
||||
<data name="Square meters-Square meters">
|
||||
<value>1</value></data>
|
||||
<data name="Square meters-Square feet">
|
||||
<value>0.09290304</value></data>
|
||||
<data name="Square meters-Square yards">
|
||||
<value>0.83612736</value></data>
|
||||
<data name="Square meters-Square millimeters">
|
||||
<value>0.000001</value></data>
|
||||
<data name="Square meters-Square centimeters">
|
||||
<value>0.0001</value></data>
|
||||
<data name="Square meters-Square inches">
|
||||
<value>0.00064516</value></data>
|
||||
<data name="Square meters-Square miles">
|
||||
<value>2589988.110336</value></data>
|
||||
<data name="Square meters-Square kilometers">
|
||||
<value>1000000</value></data>
|
||||
<data name="Square meters-Hectares">
|
||||
<value>10000</value></data>
|
||||
<data name="Square meters-hands">
|
||||
<value>0.012516104</value></data>
|
||||
<data name="Square meters-sheets of paper">
|
||||
<value>0.06032246</value></data>
|
||||
<data name="Square meters-soccer fields">
|
||||
<value>10869.66</value></data>
|
||||
<data name="Square meters-castles">
|
||||
<value>100000</value></data>
|
||||
<data name="Megabytes-Bits">
|
||||
<value>0.000000125</value></data>
|
||||
<data name="Megabytes-Bytes">
|
||||
<value>0.000001</value></data>
|
||||
<data name="Megabytes-Kilobytes">
|
||||
<value>0.001</value></data>
|
||||
<data name="Megabytes-Megabytes">
|
||||
<value>1</value></data>
|
||||
<data name="Megabytes-Gigabytes">
|
||||
<value>1000</value></data>
|
||||
<data name="Megabytes-Terabytes">
|
||||
<value>1000000</value></data>
|
||||
<data name="Megabytes-Petabytes">
|
||||
<value>1000000000</value></data>
|
||||
<data name="Megabytes-Exabytes">
|
||||
<value>1000000000000</value></data>
|
||||
<data name="Megabytes-Zetabytes">
|
||||
<value>1000000000000000</value></data>
|
||||
<data name="Megabytes-Yottabyte">
|
||||
<value>1000000000000000000</value></data>
|
||||
<data name="Megabytes-Kilobits">
|
||||
<value>0.000125</value></data>
|
||||
<data name="Megabytes-Megabits">
|
||||
<value>0.125</value></data>
|
||||
<data name="Megabytes-Gigabits">
|
||||
<value>125</value></data>
|
||||
<data name="Megabytes-Terabits">
|
||||
<value>125000</value></data>
|
||||
<data name="Megabytes-Petabits">
|
||||
<value>125000000</value></data>
|
||||
<data name="Megabytes-Exabits">
|
||||
<value>125000000000</value></data>
|
||||
<data name="Megabytes-Zetabits">
|
||||
<value>125000000000000</value></data>
|
||||
<data name="Megabytes-Yottabit">
|
||||
<value>125000000000000000</value></data>
|
||||
<data name="Megabytes-Gibibits">
|
||||
<value>134.217728</value></data>
|
||||
<data name="Megabytes-Gibibytes">
|
||||
<value>1073.741824</value></data>
|
||||
<data name="Megabytes-Kibibits">
|
||||
<value>0.000128</value></data>
|
||||
<data name="Megabytes-Kibibytes">
|
||||
<value>0.001024</value></data>
|
||||
<data name="Megabytes-Mebibits">
|
||||
<value>0.131072</value></data>
|
||||
<data name="Megabytes-Mebibytes">
|
||||
<value>1.048576</value></data>
|
||||
<data name="Megabytes-Pebibits">
|
||||
<value>140737488.355328</value></data>
|
||||
<data name="Megabytes-Pebibytes">
|
||||
<value>1125899906.842624</value></data>
|
||||
<data name="Megabytes-Tebibits">
|
||||
<value>137438.953472</value></data>
|
||||
<data name="Megabytes-Tebibytes">
|
||||
<value>1099511.627776</value></data>
|
||||
<data name="Megabytes-Exbibits">
|
||||
<value>144115188075.855872</value></data>
|
||||
<data name="Megabytes-Exbibytes">
|
||||
<value>1152921504606.846976</value></data>
|
||||
<data name="Megabytes-Zebibits">
|
||||
<value>147573952589676.412928</value></data>
|
||||
<data name="Megabytes-Zebibytes">
|
||||
<value>1180591620717411.303424</value></data>
|
||||
<data name="Megabytes-Yobibits">
|
||||
<value>151115727451828646.838272</value></data>
|
||||
<data name="Megabytes-Yobibytes">
|
||||
<value>1208925819614629174.706176</value></data>
|
||||
<data name="Megabytes-floppy disks">
|
||||
<value>1.509949</value></data>
|
||||
<data name="Megabytes-CDs">
|
||||
<value>734.003200</value></data>
|
||||
<data name="Megabytes-DVDs">
|
||||
<value>5046.586573</value></data>
|
||||
<data name="Joules-Thermal calories">
|
||||
<value>4.184</value></data>
|
||||
<data name="Joules-Food calories">
|
||||
<value>4184</value></data>
|
||||
<data name="Joules-British thermal units">
|
||||
<value>1055.056</value></data>
|
||||
<data name="Joules-Kilojoules">
|
||||
<value>1000</value></data>
|
||||
<data name="Joules-FahrenheitVolt">
|
||||
<value>0.0000000000000000001602176565</value></data>
|
||||
<data name="Joules-Joules">
|
||||
<value>1</value></data>
|
||||
<data name="Joules-Foot-pounds">
|
||||
<value>1.3558179483314</value></data>
|
||||
<data name="Joules-batteries">
|
||||
<value>9000</value></data>
|
||||
<data name="Joules-bananas">
|
||||
<value>439614</value></data>
|
||||
<data name="Joules-slices of cake">
|
||||
<value>1046700</value></data>
|
||||
<data name="Meters-Inches">
|
||||
<value>0.0254</value></data>
|
||||
<data name="Meters-Feet">
|
||||
<value>0.3048</value></data>
|
||||
<data name="Meters-Yards">
|
||||
<value>0.9144</value></data>
|
||||
<data name="Meters-Miles">
|
||||
<value>1609.344</value></data>
|
||||
<data name="Meters-Microns">
|
||||
<value>0.000001</value></data>
|
||||
<data name="Meters-Millimeters">
|
||||
<value>0.001</value></data>
|
||||
<data name="Meters-Nanometers">
|
||||
<value>0.000000001</value></data>
|
||||
<data name="Meters-Centimeters">
|
||||
<value>0.01</value></data>
|
||||
<data name="Meters-Meters">
|
||||
<value>1</value></data>
|
||||
<data name="Meters-Kilometers">
|
||||
<value>1000</value></data>
|
||||
<data name="Meters-Nautical Miles">
|
||||
<value>1852</value></data>
|
||||
<data name="Meters-paperclips">
|
||||
<value>0.035052</value></data>
|
||||
<data name="Meters-hands">
|
||||
<value>0.18669</value></data>
|
||||
<data name="Meters-jumbo jets">
|
||||
<value>76</value></data>
|
||||
<data name="Watts-British thermal unitsPerMinute">
|
||||
<value>17.58426666666667</value></data>
|
||||
<data name="Watts-Foot-pounds/minute">
|
||||
<value>0.0225969658055233</value></data>
|
||||
<data name="Watts-Watts">
|
||||
<value>1</value></data>
|
||||
<data name="Watts-Kilowatts">
|
||||
<value>1000</value></data>
|
||||
<data name="Watts-Horsepower (US)">
|
||||
<value>745.69987158227022</value></data>
|
||||
<data name="Watts-light bulbs">
|
||||
<value>60</value></data>
|
||||
<data name="Watts-horses">
|
||||
<value>745.7</value></data>
|
||||
<data name="Watts-train engines">
|
||||
<value>2982799.486329081</value></data>
|
||||
<data name="Seconds-Days">
|
||||
<value>86400</value></data>
|
||||
<data name="Seconds-Seconds">
|
||||
<value>1</value></data>
|
||||
<data name="Seconds-Weeks">
|
||||
<value>604800</value></data>
|
||||
<data name="Seconds-Years">
|
||||
<value>31557600</value></data>
|
||||
<data name="Seconds-Milliseconds">
|
||||
<value>0.001</value></data>
|
||||
<data name="Seconds-Microseconds">
|
||||
<value>0.000001</value></data>
|
||||
<data name="Seconds-Minutes">
|
||||
<value>60</value></data>
|
||||
<data name="Seconds-Hours">
|
||||
<value>3600</value></data>
|
||||
<data name="Cubic centimeters-Cups (US)">
|
||||
<value>236.588237</value></data>
|
||||
<data name="Cubic centimeters-Pints (US)">
|
||||
<value>473.176473</value></data>
|
||||
<data name="Cubic centimeters-Pints (UK)">
|
||||
<value>568.26125</value></data>
|
||||
<data name="Cubic centimeters-Quarts (US)">
|
||||
<value>946.352946</value></data>
|
||||
<data name="Cubic centimeters-Quarts (UK)">
|
||||
<value>1136.5225</value></data>
|
||||
<data name="Cubic centimeters-Gallons (US)">
|
||||
<value>3785.411784</value></data>
|
||||
<data name="Cubic centimeters-Gallons (UK)">
|
||||
<value>4546.09</value></data>
|
||||
<data name="Cubic centimeters-Liters">
|
||||
<value>1000</value></data>
|
||||
<data name="Cubic centimeters-Teaspoons (US)">
|
||||
<value>4.928922</value></data>
|
||||
<data name="Cubic centimeters-Tablespoons (US)">
|
||||
<value>14.786765</value></data>
|
||||
<data name="Cubic centimeters-Cubic centimeters">
|
||||
<value>1</value></data>
|
||||
<data name="Cubic centimeters-Cubic yards">
|
||||
<value>764554.857984</value></data>
|
||||
<data name="Cubic centimeters-Cubic meters">
|
||||
<value>1000000</value></data>
|
||||
<data name="Cubic centimeters-Milliliters">
|
||||
<value>1</value></data>
|
||||
<data name="Cubic centimeters-Cubic inches">
|
||||
<value>16.387064</value></data>
|
||||
<data name="Cubic centimeters-Cubic feet">
|
||||
<value>28316.846592</value></data>
|
||||
<data name="Cubic centimeters-Fluid ounces (US)">
|
||||
<value>29.5735295625</value></data>
|
||||
<data name="Cubic centimeters-Fluid ounces (UK)">
|
||||
<value>28.4130625</value></data>
|
||||
<data name="Cubic centimeters-Teaspoons (UK)">
|
||||
<value>5.91938802083333333333</value></data>
|
||||
<data name="Cubic centimeters-Tablespoons (UK)">
|
||||
<value>17.7581640625</value></data>
|
||||
<data name="Cubic centimeters-coffee cups">
|
||||
<value>236.5882</value></data>
|
||||
<data name="Cubic centimeters-bathtubs">
|
||||
<value>378541.2</value></data>
|
||||
<data name="Cubic centimeters-swimming pools">
|
||||
<value>3750000000</value></data>
|
||||
<data name="Kilograms-Kilograms">
|
||||
<value>1</value></data>
|
||||
<data name="Kilograms-Hectograms">
|
||||
<value>0.1</value></data>
|
||||
<data name="Kilograms-Dekagrams">
|
||||
<value>0.01</value></data>
|
||||
<data name="Kilograms-Grams">
|
||||
<value>0.001</value></data>
|
||||
<data name="Kilograms-Pounds">
|
||||
<value>0.45359237</value></data>
|
||||
<data name="Kilograms-Ounces">
|
||||
<value>0.028349523125</value></data>
|
||||
<data name="Kilograms-Milligrams">
|
||||
<value>0.000001</value></data>
|
||||
<data name="Kilograms-Centigrams">
|
||||
<value>0.00001</value></data>
|
||||
<data name="Kilograms-Decigrams">
|
||||
<value>0.0001</value></data>
|
||||
<data name="Kilograms-Long tons (UK)">
|
||||
<value>1016.0469088</value></data>
|
||||
<data name="Kilograms-Metric tonnes">
|
||||
<value>1000</value></data>
|
||||
<data name="Kilograms-Stone">
|
||||
<value>6.35029318</value></data>
|
||||
<data name="Kilograms-Carats">
|
||||
<value>0.0002</value></data>
|
||||
<data name="Kilograms-Short tons (US)">
|
||||
<value>907.18474</value></data>
|
||||
<data name="Kilograms-snowflakes">
|
||||
<value>0.000002</value></data>
|
||||
<data name="Kilograms-soccer balls">
|
||||
<value>0.4325</value></data>
|
||||
<data name="Kilograms-elephants">
|
||||
<value>4000</value></data>
|
||||
<data name="Kilograms-whales">
|
||||
<value>90000</value></data>
|
||||
<data name="CentimetersPerSecond-CentimetersPerSecond">
|
||||
<value>1</value></data>
|
||||
<data name="CentimetersPerSecond-Feet per second">
|
||||
<value>30.48</value></data>
|
||||
<data name="CentimetersPerSecond-Kilometers per hour">
|
||||
<value>27.777777777777777777778</value></data>
|
||||
<data name="CentimetersPerSecond-Knots">
|
||||
<value>51.44</value></data>
|
||||
<data name="CentimetersPerSecond-Mach">
|
||||
<value>34030</value></data>
|
||||
<data name="CentimetersPerSecond-Meters per second">
|
||||
<value>100</value></data>
|
||||
<data name="CentimetersPerSecond-Miles per hour">
|
||||
<value>44.7</value></data>
|
||||
<data name="CentimetersPerSecond-turtles">
|
||||
<value>8.94</value></data>
|
||||
<data name="CentimetersPerSecond-horses">
|
||||
<value>2011.5</value></data>
|
||||
<data name="CentimetersPerSecond-jets">
|
||||
<value>24585</value></data>
|
||||
<data name="Degrees-Degrees">
|
||||
<value>1</value></data>
|
||||
<data name="Degrees-Radians">
|
||||
<value>57.29577951308233</value></data>
|
||||
<data name="Degrees-Gradians">
|
||||
<value>0.9</value></data>
|
||||
<data name="Atmospheres-Atmospheres">
|
||||
<value>1</value></data>
|
||||
<data name="Atmospheres-Bars">
|
||||
<value>0.9869232667160128</value></data>
|
||||
<data name="Atmospheres-Kilopascals">
|
||||
<value>0.0098692326671601</value></data>
|
||||
<data name="Atmospheres-Millimeters of mercury ">
|
||||
<value>0.0013155687145324</value></data>
|
||||
<data name="Atmospheres-Pascals">
|
||||
<value>9.869232667160128e-6</value></data>
|
||||
<data name="Atmospheres-Pounds per square inch">
|
||||
<value>0.068045961016531</value></data>
|
||||
<data name="Liters-Cubic meters-2" xml:space="preserve">
|
||||
<value>0.002</value>
|
||||
</data>
|
||||
<data name="Milliliters-Cubic centimeters" xml:space="preserve">
|
||||
<value>1</value>
|
||||
</data>
|
||||
<data name="Milliliters-Cubic centimeters-1" xml:space="preserve">
|
||||
<value>1</value>
|
||||
</data>
|
||||
<data name="Milliliters-Liters" xml:space="preserve">
|
||||
<value>1000</value>
|
||||
</data>
|
||||
<data name="Milliliters-Milliliters" xml:space="preserve">
|
||||
<value>1</value>
|
||||
</data>
|
||||
<data name="Nanometers-Microns-3" xml:space="preserve">
|
||||
<value>0.003</value>
|
||||
</data>
|
||||
</root>
|
600
internal/CalculatorUnitTests/UnitConverterTest.cpp
Normal file
@@ -0,0 +1,600 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#include <WexTestClass.h>
|
||||
|
||||
using namespace UnitConversionManager;
|
||||
using namespace std;
|
||||
|
||||
namespace UnitConverterUnitTests
|
||||
{
|
||||
|
||||
void SetUnitParams(Unit* type, int id, wstring name, wstring abbreviation, bool conversionSource, bool conversionTarget, bool isWhimsical)
|
||||
{
|
||||
type->id = id;
|
||||
type->name = name;
|
||||
type->abbreviation = abbreviation;
|
||||
type->isConversionSource = conversionSource;
|
||||
type->isConversionTarget = conversionTarget;
|
||||
type->isWhimsical = isWhimsical;
|
||||
}
|
||||
|
||||
void SetCategoryParams(Category* type, int id, wstring name, bool supportsNegative)
|
||||
{
|
||||
type->id = id;
|
||||
type->name = name;
|
||||
type->supportsNegative = supportsNegative;
|
||||
}
|
||||
|
||||
void SetConversionDataParams(ConversionData* type, double ratio, double offset, bool offsetFirst)
|
||||
{
|
||||
type->ratio = ratio;
|
||||
type->offset = offset;
|
||||
type->offsetFirst = offsetFirst;
|
||||
}
|
||||
|
||||
class TestUnitConverterConfigLoader : public IConverterDataLoader
|
||||
{
|
||||
public:
|
||||
TestUnitConverterConfigLoader() :
|
||||
m_loadDataCallCount(0)
|
||||
{
|
||||
Category c1, c2;
|
||||
SetCategoryParams(&c1, 1, L"Length", true);
|
||||
SetCategoryParams(&c2, 2, L"Weight", false);
|
||||
m_categories.push_back(c1);
|
||||
m_categories.push_back(c2);
|
||||
|
||||
Unit u1, u2, u3, u4;
|
||||
SetUnitParams(&u1, 1, L"Inches", L"In", true, true, false);
|
||||
SetUnitParams(&u2, 2, L"Feet", L"Ft", false, false, false);
|
||||
SetUnitParams(&u3, 3, L"Pounds", L"Lb", true, true, false);
|
||||
SetUnitParams(&u4, 4, L"Kilograms", L"Kg", false, false, false);
|
||||
|
||||
vector<Unit> c1units = vector<Unit>();
|
||||
vector<Unit> c2units = vector<Unit>();
|
||||
c1units.push_back(u1);
|
||||
c1units.push_back(u2);
|
||||
c2units.push_back(u3);
|
||||
c2units.push_back(u4);
|
||||
|
||||
m_units[c1] = c1units;
|
||||
m_units[c2] = c2units;
|
||||
|
||||
unordered_map<Unit, ConversionData, UnitHash> unit1Map = unordered_map<Unit, ConversionData, UnitHash>();
|
||||
unordered_map<Unit, ConversionData, UnitHash> unit2Map = unordered_map<Unit, ConversionData, UnitHash>();
|
||||
unordered_map<Unit, ConversionData, UnitHash> unit3Map = unordered_map<Unit, ConversionData, UnitHash>();
|
||||
unordered_map<Unit, ConversionData, UnitHash> unit4Map = unordered_map<Unit, ConversionData, UnitHash>();
|
||||
|
||||
ConversionData conversion1, conversion2, conversion3, conversion4, conversion5;
|
||||
SetConversionDataParams(&conversion1, 1.0, 0, false);
|
||||
SetConversionDataParams(&conversion2, 0.08333333333333333333333333333333, 0, false);
|
||||
SetConversionDataParams(&conversion3, 12.0, 0, false);
|
||||
SetConversionDataParams(&conversion4, 0.453592, 0, false);
|
||||
SetConversionDataParams(&conversion5, 2.20462, 0, false);
|
||||
|
||||
//Setting the conversion ratios for testing
|
||||
unit1Map[u1] = conversion1;
|
||||
unit1Map[u2] = conversion2;
|
||||
|
||||
unit2Map[u1] = conversion3;
|
||||
unit2Map[u2] = conversion1;
|
||||
|
||||
unit3Map[u3] = conversion1;
|
||||
unit3Map[u4] = conversion4;
|
||||
|
||||
unit4Map[u3] = conversion5;
|
||||
unit4Map[u4] = conversion1;
|
||||
|
||||
|
||||
m_ratioMaps[u1] = unit1Map;
|
||||
m_ratioMaps[u2] = unit2Map;
|
||||
m_ratioMaps[u3] = unit3Map;
|
||||
m_ratioMaps[u4] = unit4Map;
|
||||
}
|
||||
|
||||
void LoadData()
|
||||
{
|
||||
m_loadDataCallCount++;
|
||||
}
|
||||
|
||||
vector<Category> LoadOrderedCategories()
|
||||
{
|
||||
return m_categories;
|
||||
}
|
||||
|
||||
vector<Unit> LoadOrderedUnits(const Category& c)
|
||||
{
|
||||
return m_units[c];
|
||||
}
|
||||
|
||||
unordered_map<Unit, ConversionData, UnitHash> LoadOrderedRatios(const Unit& u)
|
||||
{
|
||||
return m_ratioMaps[u];
|
||||
}
|
||||
|
||||
bool SupportsCategory(const Category& target)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
UINT m_loadDataCallCount;
|
||||
private:
|
||||
vector<Category> m_categories;
|
||||
CategoryToUnitVectorMap m_units;
|
||||
UnitToUnitToConversionDataMap m_ratioMaps;
|
||||
};
|
||||
|
||||
class TestUnitConverterVMCallback : public IUnitConverterVMCallback
|
||||
{
|
||||
public:
|
||||
void Reset()
|
||||
{
|
||||
m_maxDigitsReachedCallCount = 0;
|
||||
}
|
||||
|
||||
void DisplayCallback(const wstring& from, const wstring& to) override
|
||||
{
|
||||
m_lastFrom = from;
|
||||
m_lastTo = to;
|
||||
}
|
||||
|
||||
void SuggestedValueCallback(const vector<tuple<wstring, Unit>>& suggestedValues) override
|
||||
{
|
||||
m_lastSuggested = suggestedValues;
|
||||
}
|
||||
|
||||
void MaxDigitsReached() override
|
||||
{
|
||||
m_maxDigitsReachedCallCount++;
|
||||
}
|
||||
|
||||
int GetMaxDigitsReachedCallCount()
|
||||
{
|
||||
return m_maxDigitsReachedCallCount;
|
||||
}
|
||||
|
||||
bool CheckDisplayValues(wstring from, wstring to)
|
||||
{
|
||||
return (from == m_lastFrom && to == m_lastTo);
|
||||
}
|
||||
|
||||
bool CheckSuggestedValues(vector<tuple<wstring, Unit>> suggested)
|
||||
{
|
||||
if (suggested.size() != m_lastSuggested.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool returnValue = true;
|
||||
for (unsigned int i = 0; i < suggested.size(); i++)
|
||||
{
|
||||
if (suggested[i] != m_lastSuggested[i])
|
||||
{
|
||||
returnValue = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
private:
|
||||
wstring m_lastFrom;
|
||||
wstring m_lastTo;
|
||||
vector<tuple<wstring, Unit>> m_lastSuggested;
|
||||
int m_maxDigitsReachedCallCount = 0;
|
||||
};
|
||||
|
||||
class UnitConverterTest
|
||||
{
|
||||
public:
|
||||
// Declare this class as a TestClass, and supply metadata if necessary.
|
||||
TEST_CLASS(UnitConverterTest);
|
||||
TEST_CLASS_SETUP(CommonSetup);
|
||||
|
||||
TEST_METHOD_CLEANUP(Cleanup);
|
||||
|
||||
TEST_METHOD(UnitConverterTestInit);
|
||||
TEST_METHOD(UnitConverterTestBasic);
|
||||
TEST_METHOD(UnitConverterTestGetters);
|
||||
TEST_METHOD(UnitConverterTestGetCategory);
|
||||
TEST_METHOD(UnitConverterTestUnitTypeSwitching);
|
||||
TEST_METHOD(UnitConverterTestSerialization);
|
||||
TEST_METHOD(UnitConverterTestDeSerialization);
|
||||
TEST_METHOD(UnitConverterTestQuote);
|
||||
TEST_METHOD(UnitConverterTestUnquote);
|
||||
TEST_METHOD(UnitConverterTestBackspace);
|
||||
TEST_METHOD(UnitConverterTestScientificInputs);
|
||||
TEST_METHOD(UnitConverterTestSupplementaryResultRounding);
|
||||
TEST_METHOD(UnitConverterTestMaxDigitsReached);
|
||||
TEST_METHOD(UnitConverterTestMaxDigitsReached_LeadingDecimal);
|
||||
TEST_METHOD(UnitConverterTestMaxDigitsReached_TrailingDecimal);
|
||||
TEST_METHOD(UnitConverterTestMaxDigitsReached_MultipleTimes);
|
||||
private:
|
||||
static void ExecuteCommands(vector<Command> commands);
|
||||
|
||||
static shared_ptr<UnitConverter> s_unitConverter;
|
||||
static shared_ptr<TestUnitConverterConfigLoader> s_xmlLoader;
|
||||
static shared_ptr<TestUnitConverterVMCallback> s_testVMCallback;
|
||||
static Category s_testLength;
|
||||
static Category s_testWeight;
|
||||
static Unit s_testInches;
|
||||
static Unit s_testFeet;
|
||||
static Unit s_testPounds;
|
||||
static Unit s_testKilograms;
|
||||
};
|
||||
|
||||
shared_ptr<UnitConverter> UnitConverterTest::s_unitConverter;
|
||||
shared_ptr<TestUnitConverterConfigLoader> UnitConverterTest::s_xmlLoader;
|
||||
shared_ptr<TestUnitConverterVMCallback> UnitConverterTest::s_testVMCallback;
|
||||
Category UnitConverterTest::s_testLength;
|
||||
Category UnitConverterTest::s_testWeight;
|
||||
Unit UnitConverterTest::s_testInches;
|
||||
Unit UnitConverterTest::s_testFeet;
|
||||
Unit UnitConverterTest::s_testPounds;
|
||||
Unit UnitConverterTest::s_testKilograms;
|
||||
|
||||
// Creates instance of UnitConverter before running tests
|
||||
bool UnitConverterTest::CommonSetup()
|
||||
{
|
||||
s_testVMCallback = make_shared<TestUnitConverterVMCallback>();
|
||||
s_xmlLoader = make_shared<TestUnitConverterConfigLoader>();
|
||||
s_unitConverter = make_shared<UnitConverter>(s_xmlLoader);
|
||||
s_unitConverter->SetViewModelCallback(s_testVMCallback);
|
||||
SetCategoryParams(&s_testLength, 1, L"Length", true);
|
||||
SetCategoryParams(&s_testWeight, 2, L"Weight", false);
|
||||
SetUnitParams(&s_testInches, 1, L"Inches", L"In", true, true, false);
|
||||
SetUnitParams(&s_testFeet, 2, L"Feet", L"Ft", false, false, false);
|
||||
SetUnitParams(&s_testPounds, 3, L"Pounds", L"Lb", true, true, false);
|
||||
SetUnitParams(&s_testKilograms, 4, L"Kilograms", L"Kg", false, false, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Resets calculator state to start state after each test
|
||||
bool UnitConverterTest::Cleanup()
|
||||
{
|
||||
s_unitConverter->DeSerialize(wstring());
|
||||
s_testVMCallback->Reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
void UnitConverterTest::ExecuteCommands(vector<Command> commands)
|
||||
{
|
||||
for (size_t i = 0; i < commands.size() && commands[i] != Command::None; i++)
|
||||
{
|
||||
s_unitConverter->SendCommand(commands[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Test ctor/initialization states
|
||||
void UnitConverterTest::UnitConverterTestInit()
|
||||
{
|
||||
VERIFY_ARE_EQUAL((UINT)0, s_xmlLoader->m_loadDataCallCount); // shouldn't have initialized the loader yet
|
||||
s_unitConverter->Initialize();
|
||||
VERIFY_ARE_EQUAL((UINT)1, s_xmlLoader->m_loadDataCallCount); // now we should have loaded
|
||||
}
|
||||
|
||||
// Verify a basic input command stream.'3', '2', '.', '0'
|
||||
void UnitConverterTest::UnitConverterTestBasic()
|
||||
{
|
||||
tuple<wstring, Unit> test1[] = {tuple<wstring,Unit>(wstring(L"0.25"), s_testFeet)};
|
||||
tuple<wstring, Unit> test2[] = {tuple<wstring,Unit>(wstring(L"2.5"), s_testFeet)};
|
||||
|
||||
s_unitConverter->SendCommand(Command::Three);
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckDisplayValues(wstring(L"3"), wstring(L"3")));
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckSuggestedValues(vector<tuple<wstring, Unit>>(begin(test1),end(test1))));
|
||||
s_unitConverter->SendCommand(Command::Zero);
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckDisplayValues(wstring(L"30"), wstring(L"30")));
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckSuggestedValues(vector<tuple<wstring, Unit>>(begin(test2),end(test2))));
|
||||
s_unitConverter->SendCommand(Command::Decimal);
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckDisplayValues(wstring(L"30."), wstring(L"30")));
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckSuggestedValues(vector<tuple<wstring, Unit>>(begin(test2),end(test2))));
|
||||
s_unitConverter->SendCommand(Command::Zero);
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckDisplayValues(wstring(L"30.0"), wstring(L"30")));
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckSuggestedValues(vector<tuple<wstring, Unit>>(begin(test2),end(test2))));
|
||||
}
|
||||
|
||||
// Check the getter functions
|
||||
void UnitConverterTest::UnitConverterTestGetters()
|
||||
{
|
||||
Category test1[] = {s_testLength, s_testWeight};
|
||||
Unit test2[] = {s_testInches, s_testFeet};
|
||||
|
||||
VERIFY_IS_TRUE(s_unitConverter->GetCategories() == vector<Category>(begin(test1),end(test1)));
|
||||
VERIFY_IS_TRUE(get<0>(s_unitConverter->SetCurrentCategory(test1[0])) == vector<Unit>(begin(test2),end(test2)));
|
||||
}
|
||||
|
||||
// Test getting category after it has been set.
|
||||
void UnitConverterTest::UnitConverterTestGetCategory()
|
||||
{
|
||||
s_unitConverter->SetCurrentCategory(s_testWeight);
|
||||
VERIFY_IS_TRUE(s_unitConverter->GetCurrentCategory() == s_testWeight);
|
||||
}
|
||||
|
||||
// Test switching of unit types
|
||||
void UnitConverterTest::UnitConverterTestUnitTypeSwitching()
|
||||
{
|
||||
// Enter 57 into the from field, then switch focus to the to field (making it the new from field)
|
||||
s_unitConverter->SendCommand(Command::Five);
|
||||
s_unitConverter->SendCommand(Command::Seven);
|
||||
s_unitConverter->SwitchActive(wstring(L"57"));
|
||||
// Now set unit conversion to go from kilograms to pounds
|
||||
s_unitConverter->SetCurrentCategory(s_testWeight);
|
||||
s_unitConverter->SetCurrentUnitTypes(s_testKilograms, s_testPounds);
|
||||
s_unitConverter->SendCommand(Command::Five);
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckDisplayValues(wstring(L"5"), wstring(L"11.0231")));
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckSuggestedValues(vector<tuple<wstring, Unit>>()));
|
||||
}
|
||||
|
||||
// Test serialization
|
||||
void UnitConverterTest::UnitConverterTestSerialization()
|
||||
{
|
||||
wstring test1 = wstring(L"4;Kilograms;Kg;0;0;0;|3;Pounds;Lb;1;1;0;|2;0;Weight;|1;1;0;52.8;116.4039;|1;1;Length;,2;0;Weight;,|1;1;Length;[1;Inches;In;1;1;0;,2;Feet;Ft;0;0;0;,[]2;0;Weight;[3;Pounds;Lb;1;1;0;,4;Kilograms;Kg;0;0;0;,[]|1;Inches;In;1;1;0;[1;Inches;In;1;1;0;:1;0;0;:,2;Feet;Ft;0;0;0;:0.08333333333333332870740406406185;0;0;:,[]2;Feet;Ft;0;0;0;[1;Inches;In;1;1;0;:12;0;0;:,2;Feet;Ft;0;0;0;:1;0;0;:,[]3;Pounds;Lb;1;1;0;[3;Pounds;Lb;1;1;0;:1;0;0;:,4;Kilograms;Kg;0;0;0;:0.45359199999999999519673110626172;0;0;:,[]4;Kilograms;Kg;0;0;0;[3;Pounds;Lb;1;1;0;:2.20461999999999980204279381723609;0;0;:,4;Kilograms;Kg;0;0;0;:1;0;0;:,[]|");
|
||||
s_unitConverter->SendCommand(Command::Five);
|
||||
s_unitConverter->SendCommand(Command::Two);
|
||||
s_unitConverter->SendCommand(Command::Decimal);
|
||||
s_unitConverter->SendCommand(Command::Eight);
|
||||
s_unitConverter->SetCurrentCategory(s_testWeight);
|
||||
s_unitConverter->SetCurrentUnitTypes(s_testKilograms, s_testPounds);
|
||||
VERIFY_IS_TRUE(s_unitConverter->Serialize().compare(test1) == 0);
|
||||
}
|
||||
|
||||
// Test input escaping
|
||||
void UnitConverterTest::UnitConverterTestQuote()
|
||||
{
|
||||
wstring input1 = L"Weight";
|
||||
wstring output1 = L"Weight";
|
||||
wstring input2 = L"{p}Weig;[ht|";
|
||||
wstring output2 = L"{lb}p{rb}Weig{sc}{lc}ht{p}";
|
||||
wstring input3 = L"{{{t;s}}},:]";
|
||||
wstring output3 = L"{lb}{lb}{lb}t{sc}s{rb}{rb}{rb}{cm}{co}{rc}";
|
||||
VERIFY_IS_TRUE(UnitConverter::Quote(input1) == output1);
|
||||
VERIFY_IS_TRUE(UnitConverter::Quote(input2) == output2);
|
||||
VERIFY_IS_TRUE(UnitConverter::Quote(input3) == output3);
|
||||
}
|
||||
|
||||
// Test output unescaping
|
||||
void UnitConverterTest::UnitConverterTestUnquote()
|
||||
{
|
||||
wstring input1 = L"Weight";
|
||||
wstring input2 = L"{p}Weig;[ht|";
|
||||
wstring input3 = L"{{{t;s}}},:]";
|
||||
VERIFY_IS_TRUE(UnitConverter::Unquote(input1) == input1);
|
||||
VERIFY_IS_TRUE(UnitConverter::Unquote(UnitConverter::Quote(input1)) == input1);
|
||||
VERIFY_IS_TRUE(UnitConverter::Unquote(UnitConverter::Quote(input2)) == input2);
|
||||
VERIFY_IS_TRUE(UnitConverter::Unquote(UnitConverter::Quote(input3)) == input3);
|
||||
}
|
||||
|
||||
// Test de-serialization
|
||||
void UnitConverterTest::UnitConverterTestDeSerialization()
|
||||
{
|
||||
wstring test1 = wstring(L"4;Kilograms;Kg;0;0;0;|3;Pounds;Lb;1;1;0;|2;0;Weight;|1;1;0;52.8;116.4039;|1;1;Length;,2;0;Weight;,|1;1;Length;[1;Inches;In;1;1;0;,2;Feet;Ft;0;0;0;,[]2;0;Weight;[3;Pounds;Lb;1;1;0;,4;Kilograms;Kg;0;0;0;,[]|1;Inches;In;1;1;0;[1;Inches;In;1;1;0;:1;0;0;:,2;Feet;Ft;0;0;0;:0.08333333333333332870740406406185;0;0;:,[]2;Feet;Ft;0;0;0;[1;Inches;In;1;1;0;:12;0;0;:,2;Feet;Ft;0;0;0;:1;0;0;:,[]3;Pounds;Lb;1;1;0;[3;Pounds;Lb;1;1;0;:1;0;0;:,4;Kilograms;Kg;0;0;0;:0.45359199999999999519673110626172;0;0;:,[]4;Kilograms;Kg;0;0;0;[3;Pounds;Lb;1;1;0;:2.20461999999999980204279381723609;0;0;:,4;Kilograms;Kg;0;0;0;:1;0;0;:,[]|");
|
||||
s_unitConverter->DeSerialize(test1);
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckDisplayValues(wstring(L"52.8"), wstring(L"116.4039")));
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckSuggestedValues(vector<tuple<wstring, Unit>>()));
|
||||
}
|
||||
|
||||
// Test backspace commands
|
||||
void UnitConverterTest::UnitConverterTestBackspace()
|
||||
{
|
||||
tuple<wstring, Unit> test1[] = {tuple<wstring,Unit>(wstring(L"13.66"), s_testKilograms)};
|
||||
tuple<wstring, Unit> test2[] = {tuple<wstring,Unit>(wstring(L"13.65"), s_testKilograms)};
|
||||
tuple<wstring, Unit> test3[] = {tuple<wstring,Unit>(wstring(L"13.61"), s_testKilograms)};
|
||||
tuple<wstring, Unit> test4[] = {tuple<wstring,Unit>(wstring(L"1.36"), s_testKilograms)};
|
||||
|
||||
s_unitConverter->SetCurrentCategory(s_testWeight);
|
||||
s_unitConverter->SetCurrentUnitTypes(s_testPounds, s_testPounds);
|
||||
s_unitConverter->SendCommand(Command::Three);
|
||||
s_unitConverter->SendCommand(Command::Zero);
|
||||
s_unitConverter->SendCommand(Command::Decimal);
|
||||
s_unitConverter->SendCommand(Command::One);
|
||||
s_unitConverter->SendCommand(Command::Two);
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckDisplayValues(wstring(L"30.12"), wstring(L"30.12")));
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckSuggestedValues(vector<tuple<wstring, Unit>>(begin(test1),end(test1))));
|
||||
s_unitConverter->SendCommand(Command::Backspace);
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckDisplayValues(wstring(L"30.1"), wstring(L"30.1")));
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckSuggestedValues(vector<tuple<wstring, Unit>>(begin(test2),end(test2))));
|
||||
s_unitConverter->SendCommand(Command::Backspace);
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckDisplayValues(wstring(L"30."), wstring(L"30")));
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckSuggestedValues(vector<tuple<wstring, Unit>>(begin(test3),end(test3))));
|
||||
s_unitConverter->SendCommand(Command::Backspace);
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckDisplayValues(wstring(L"30"), wstring(L"30")));
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckSuggestedValues(vector<tuple<wstring, Unit>>(begin(test3),end(test3))));
|
||||
s_unitConverter->SendCommand(Command::Backspace);
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckDisplayValues(wstring(L"3"), wstring(L"3")));
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckSuggestedValues(vector<tuple<wstring, Unit>>(begin(test4),end(test4))));
|
||||
s_unitConverter->SendCommand(Command::Backspace);
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckDisplayValues(wstring(L"0"), wstring(L"0")));
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckSuggestedValues(vector<tuple<wstring, Unit>>()));
|
||||
}
|
||||
|
||||
// Test large values
|
||||
void UnitConverterTest::UnitConverterTestScientificInputs()
|
||||
{
|
||||
s_unitConverter->SetCurrentCategory(s_testWeight);
|
||||
s_unitConverter->SetCurrentUnitTypes(s_testPounds, s_testKilograms);
|
||||
s_unitConverter->SendCommand(Command::Decimal);
|
||||
s_unitConverter->SendCommand(Command::Zero);
|
||||
s_unitConverter->SendCommand(Command::Zero);
|
||||
s_unitConverter->SendCommand(Command::Zero);
|
||||
s_unitConverter->SendCommand(Command::Zero);
|
||||
s_unitConverter->SendCommand(Command::Zero);
|
||||
s_unitConverter->SendCommand(Command::Zero);
|
||||
s_unitConverter->SendCommand(Command::Zero);
|
||||
s_unitConverter->SendCommand(Command::Zero);
|
||||
s_unitConverter->SendCommand(Command::Zero);
|
||||
s_unitConverter->SendCommand(Command::Zero);
|
||||
s_unitConverter->SendCommand(Command::Zero);
|
||||
s_unitConverter->SendCommand(Command::Zero);
|
||||
s_unitConverter->SendCommand(Command::Zero);
|
||||
s_unitConverter->SendCommand(Command::One);
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckDisplayValues(wstring(L"0.00000000000001"), wstring(L"4.535920e-15")));
|
||||
s_unitConverter->SwitchActive(wstring(L"4.535920e-15"));
|
||||
s_unitConverter->SendCommand(Command::Nine);
|
||||
s_unitConverter->SendCommand(Command::Nine);
|
||||
s_unitConverter->SendCommand(Command::Nine);
|
||||
s_unitConverter->SendCommand(Command::Nine);
|
||||
s_unitConverter->SendCommand(Command::Nine);
|
||||
s_unitConverter->SendCommand(Command::Nine);
|
||||
s_unitConverter->SendCommand(Command::Nine);
|
||||
s_unitConverter->SendCommand(Command::Nine);
|
||||
s_unitConverter->SendCommand(Command::Nine);
|
||||
s_unitConverter->SendCommand(Command::Nine);
|
||||
s_unitConverter->SendCommand(Command::Nine);
|
||||
s_unitConverter->SendCommand(Command::Nine);
|
||||
s_unitConverter->SendCommand(Command::Nine);
|
||||
s_unitConverter->SendCommand(Command::Nine);
|
||||
s_unitConverter->SendCommand(Command::Nine);
|
||||
s_unitConverter->SendCommand(Command::Nine);
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckDisplayValues(wstring(L"999999999999999"), wstring(L"2.204620e+15")));
|
||||
s_unitConverter->SwitchActive(wstring(L"2.20463e+15"));
|
||||
s_unitConverter->SendCommand(Command::One);
|
||||
s_unitConverter->SendCommand(Command::Two);
|
||||
s_unitConverter->SendCommand(Command::Three);
|
||||
s_unitConverter->SendCommand(Command::Four);
|
||||
s_unitConverter->SendCommand(Command::Five);
|
||||
s_unitConverter->SendCommand(Command::Six);
|
||||
s_unitConverter->SendCommand(Command::Seven);
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckDisplayValues(wstring(L"1234567"), wstring(L"559989.7")));
|
||||
s_unitConverter->SwitchActive(wstring(L"559989.7"));
|
||||
s_unitConverter->SendCommand(Command::One);
|
||||
s_unitConverter->SendCommand(Command::Two);
|
||||
s_unitConverter->SendCommand(Command::Three);
|
||||
s_unitConverter->SendCommand(Command::Four);
|
||||
s_unitConverter->SendCommand(Command::Five);
|
||||
s_unitConverter->SendCommand(Command::Six);
|
||||
s_unitConverter->SendCommand(Command::Seven);
|
||||
s_unitConverter->SendCommand(Command::Eight);
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckDisplayValues(wstring(L"12345678"), wstring(L"27217528.63236")));
|
||||
}
|
||||
|
||||
// Test large values
|
||||
void UnitConverterTest::UnitConverterTestSupplementaryResultRounding()
|
||||
{
|
||||
tuple<wstring, Unit> test1[] = {tuple<wstring,Unit>(wstring(L"27.75"), s_testFeet)};
|
||||
tuple<wstring, Unit> test2[] = {tuple<wstring,Unit>(wstring(L"277.8"), s_testFeet)};
|
||||
tuple<wstring, Unit> test3[] = {tuple<wstring,Unit>(wstring(L"2778"), s_testFeet)};
|
||||
s_unitConverter->SendCommand(Command::Three);
|
||||
s_unitConverter->SendCommand(Command::Three);
|
||||
s_unitConverter->SendCommand(Command::Three);
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckSuggestedValues(vector<tuple<wstring, Unit>>(begin(test1),end(test1))));
|
||||
s_unitConverter->SendCommand(Command::Three);
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckSuggestedValues(vector<tuple<wstring, Unit>>(begin(test2),end(test2))));
|
||||
s_unitConverter->SendCommand(Command::Three);
|
||||
VERIFY_IS_TRUE(s_testVMCallback->CheckSuggestedValues(vector<tuple<wstring, Unit>>(begin(test3),end(test3))));
|
||||
}
|
||||
|
||||
void UnitConverterTest::UnitConverterTestMaxDigitsReached()
|
||||
{
|
||||
ExecuteCommands({
|
||||
Command::One,
|
||||
Command::Two,
|
||||
Command::Three,
|
||||
Command::Four,
|
||||
Command::Five,
|
||||
Command::Six,
|
||||
Command::Seven,
|
||||
Command::Eight,
|
||||
Command::Nine,
|
||||
Command::One,
|
||||
Command::Zero,
|
||||
Command::One,
|
||||
Command::One,
|
||||
Command::One,
|
||||
Command::Two
|
||||
});
|
||||
|
||||
VERIFY_ARE_EQUAL(0, s_testVMCallback->GetMaxDigitsReachedCallCount());
|
||||
|
||||
ExecuteCommands({ Command::One });
|
||||
|
||||
VERIFY_ARE_EQUAL(1, s_testVMCallback->GetMaxDigitsReachedCallCount());
|
||||
}
|
||||
|
||||
void UnitConverterTest::UnitConverterTestMaxDigitsReached_LeadingDecimal()
|
||||
{
|
||||
ExecuteCommands({
|
||||
Command::Zero,
|
||||
Command::Decimal,
|
||||
Command::One,
|
||||
Command::Two,
|
||||
Command::Three,
|
||||
Command::Four,
|
||||
Command::Five,
|
||||
Command::Six,
|
||||
Command::Seven,
|
||||
Command::Eight,
|
||||
Command::Nine,
|
||||
Command::One,
|
||||
Command::Zero,
|
||||
Command::One,
|
||||
Command::One,
|
||||
Command::One
|
||||
});
|
||||
|
||||
VERIFY_ARE_EQUAL(0, s_testVMCallback->GetMaxDigitsReachedCallCount());
|
||||
|
||||
ExecuteCommands({ Command::Two });
|
||||
|
||||
VERIFY_ARE_EQUAL(1, s_testVMCallback->GetMaxDigitsReachedCallCount());
|
||||
}
|
||||
|
||||
void UnitConverterTest::UnitConverterTestMaxDigitsReached_TrailingDecimal()
|
||||
{
|
||||
ExecuteCommands({
|
||||
Command::One,
|
||||
Command::Two,
|
||||
Command::Three,
|
||||
Command::Four,
|
||||
Command::Five,
|
||||
Command::Six,
|
||||
Command::Seven,
|
||||
Command::Eight,
|
||||
Command::Nine,
|
||||
Command::One,
|
||||
Command::Zero,
|
||||
Command::One,
|
||||
Command::One,
|
||||
Command::One,
|
||||
Command::Two,
|
||||
Command::Decimal
|
||||
});
|
||||
|
||||
VERIFY_ARE_EQUAL(0, s_testVMCallback->GetMaxDigitsReachedCallCount());
|
||||
|
||||
ExecuteCommands({ Command::One });
|
||||
|
||||
VERIFY_ARE_EQUAL(1, s_testVMCallback->GetMaxDigitsReachedCallCount());
|
||||
}
|
||||
|
||||
void UnitConverterTest::UnitConverterTestMaxDigitsReached_MultipleTimes()
|
||||
{
|
||||
ExecuteCommands({
|
||||
Command::One,
|
||||
Command::Two,
|
||||
Command::Three,
|
||||
Command::Four,
|
||||
Command::Five,
|
||||
Command::Six,
|
||||
Command::Seven,
|
||||
Command::Eight,
|
||||
Command::Nine,
|
||||
Command::One,
|
||||
Command::Zero,
|
||||
Command::One,
|
||||
Command::One,
|
||||
Command::One,
|
||||
Command::Two
|
||||
});
|
||||
|
||||
VERIFY_ARE_EQUAL(0, s_testVMCallback->GetMaxDigitsReachedCallCount());
|
||||
|
||||
for (auto count = 1; count <= 10; count++)
|
||||
{
|
||||
ExecuteCommands({ Command::Three });
|
||||
|
||||
VERIFY_ARE_EQUAL(count, s_testVMCallback->GetMaxDigitsReachedCallCount(), to_wstring(count).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1115
internal/CalculatorUnitTests/UnitConverterViewModelUnitTests.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
namespace UCM = UnitConversionManager;
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace CalculatorUnitTests
|
||||
{
|
||||
static UCM::Unit UNIT1 = { 1, L"UNIT1", L"U1", true, false, false };
|
||||
static UCM::Unit UNIT2 = { 2, L"UNIT2", L"U2", false, true, false };
|
||||
static UCM::Unit UNIT3 = { 3, L"UNIT3", L"U3", false, false, false };
|
||||
static UCM::Unit UNIT4 = { 4, L"UNIT4", L"U4", true, false, false };
|
||||
static UCM::Unit UNIT5 = { 5, L"UNIT5", L"U5", false, false, false };
|
||||
static UCM::Unit UNIT6 = { 6, L"UNIT6", L"U6", false, true, false };
|
||||
static UCM::Unit UNIT7 = { 7, L"UNIT7", L"U7", false, true, false };
|
||||
static UCM::Unit UNIT8 = { 8, L"UNIT8", L"U8", false, false, false };
|
||||
static UCM::Unit UNIT9 = { 9, L"UNIT9", L"U9", true, false, false };
|
||||
static UCM::Unit UNITWHIMSY = { 10, L"Whimsy", L"UW", true, false, true };
|
||||
|
||||
static UCM::Category CAT1 = { 1, L"CAT1", false }; // contains Unit1 - Unit3
|
||||
static UCM::Category CAT2 = { 2, L"CAT2", false }; // contains Unit4 - Unit6
|
||||
static UCM::Category CAT3 = { 3, L"CAT3", false }; // contains Unit7 - Unit9
|
||||
|
||||
|
||||
class UnitConverterMock : public UnitConversionManager::IUnitConverter
|
||||
{
|
||||
public:
|
||||
UnitConverterMock();
|
||||
void Initialize() override;
|
||||
std::vector<UCM::Category> GetCategories() override;
|
||||
UCM::CategorySelectionInitializer SetCurrentCategory(const UCM::Category& input) override;
|
||||
UCM::Category GetCurrentCategory();
|
||||
void SetCurrentUnitTypes(const UCM::Unit& fromType, const UCM::Unit& toType) override;
|
||||
void SwitchActive(const std::wstring& newValue);
|
||||
std::wstring Serialize() override;
|
||||
void DeSerialize(const std::wstring& serializedData) override;
|
||||
std::wstring SaveUserPreferences() override;
|
||||
void RestoreUserPreferences(_In_ const std::wstring& userPreferences) override;
|
||||
void SendCommand(UCM::Command command) override;
|
||||
void SetViewModelCallback(const std::shared_ptr<UCM::IUnitConverterVMCallback>& newCallback) override;
|
||||
void SetViewModelCurrencyCallback(_In_ const std::shared_ptr<UCM::IViewModelCurrencyCallback>& newCallback) override {}
|
||||
concurrency::task<std::pair<bool, std::wstring>> RefreshCurrencyRatios() override
|
||||
{
|
||||
co_return std::make_pair(L"", L"");
|
||||
}
|
||||
|
||||
UINT m_initCallCount;
|
||||
UINT m_getCategoriesCallCount;
|
||||
UINT m_setCurrentCategoryCallCount;
|
||||
UINT m_setCurUnitTypesCallCount;
|
||||
UINT m_switchActiveCallCount;
|
||||
UINT m_sendCommandCallCount;
|
||||
UINT m_setVMCallbackCallCount;
|
||||
UINT m_serializeCallCount;
|
||||
UINT m_deSerializeCallCount;
|
||||
|
||||
UCM::Category m_curCategory;
|
||||
UCM::Unit m_curFrom;
|
||||
UCM::Unit m_curTo;
|
||||
UCM::Command m_lastCommand;
|
||||
|
||||
std::shared_ptr<UCM::IUnitConverterVMCallback> m_vmCallback;
|
||||
std::vector<std::tuple<std::wstring, UCM::Unit>> m_suggestedList;
|
||||
std::wstring m_curValue;
|
||||
};
|
||||
}
|
||||
|
30
internal/CalculatorUnitTests/UnitTestApp.rd.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<!--
|
||||
This file contains Runtime Directives used by .NET Native. The defaults here are suitable for most
|
||||
developers. However, you can modify these parameters to modify the behavior of the .NET Native
|
||||
optimizer.
|
||||
|
||||
Runtime Directives are documented at http://go.microsoft.com/fwlink/?LinkID=391919
|
||||
|
||||
To fully enable reflection for App1.MyClass and all of its public/private members
|
||||
<Type Name="App1.MyClass" Dynamic="Required All"/>
|
||||
|
||||
To enable dynamic creation of the specific instantiation of AppClass<T> over System.Int32
|
||||
<TypeInstantiation Name="App1.AppClass" Arguments="System.Int32" Activate="Required Public" />
|
||||
|
||||
Using the Namespace directive to apply reflection policy to all the types in a particular namespace
|
||||
<Namespace Name="DataClasses.ViewModels" Seralize="All" />
|
||||
-->
|
||||
|
||||
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
|
||||
<Application>
|
||||
<!--
|
||||
An Assembly element with Name="*Application*" applies to all assemblies in
|
||||
the application package. The asterisks are not wildcards.
|
||||
-->
|
||||
<Assembly Name="*Application*" Dynamic="Required All" />
|
||||
|
||||
<!-- Add your application specific runtime directives here. -->
|
||||
|
||||
|
||||
</Application>
|
||||
</Directives>
|
8
internal/CalculatorUnitTests/UnitTestApp.xaml
Normal file
@@ -0,0 +1,8 @@
|
||||
<Application
|
||||
x:Class="CalculatorUnitTests.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:CalculatorUnitTests"
|
||||
RequestedTheme="Light">
|
||||
|
||||
</Application>
|
111
internal/CalculatorUnitTests/UnitTestApp.xaml.cpp
Normal file
@@ -0,0 +1,111 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
//
|
||||
// App.xaml.cpp
|
||||
// Implementation of the App class.
|
||||
//
|
||||
|
||||
#include "pch.h"
|
||||
#include "UnitTestApp.xaml.h"
|
||||
|
||||
using namespace CalculatorUnitTests;
|
||||
|
||||
using namespace Platform;
|
||||
using namespace Windows::ApplicationModel;
|
||||
using namespace Windows::ApplicationModel::Activation;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
using namespace Windows::UI::Xaml::Controls::Primitives;
|
||||
using namespace Windows::UI::Xaml::Data;
|
||||
using namespace Windows::UI::Xaml::Input;
|
||||
using namespace Windows::UI::Xaml::Interop;
|
||||
using namespace Windows::UI::Xaml::Media;
|
||||
using namespace Windows::UI::Xaml::Navigation;
|
||||
|
||||
// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=402347&clcid=0x409
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the singleton application object. This is the first line of authored code
|
||||
/// executed, and as such is the logical equivalent of main() or WinMain().
|
||||
/// </summary>
|
||||
App::App()
|
||||
{
|
||||
InitializeComponent();
|
||||
Suspending += ref new SuspendingEventHandler(this, &App::OnSuspending);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when the application is launched normally by the end user. Other entry points
|
||||
/// will be used such as when the application is launched to open a specific file.
|
||||
/// </summary>
|
||||
/// <param name="e">Details about the launch request and process.</param>
|
||||
void App::OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ e)
|
||||
{
|
||||
|
||||
#if _DEBUG
|
||||
// Show graphics profiling information while debugging.
|
||||
if (IsDebuggerPresent())
|
||||
{
|
||||
// Display the current frame rate counters
|
||||
DebugSettings->EnableFrameRateCounter = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
auto rootFrame = dynamic_cast<Frame^>(Window::Current->Content);
|
||||
|
||||
// Do not repeat app initialization when the Window already has content,
|
||||
// just ensure that the window is active
|
||||
if (rootFrame == nullptr)
|
||||
{
|
||||
// Create a Frame to act as the navigation context and associate it with
|
||||
// a SuspensionManager key
|
||||
rootFrame = ref new Frame();
|
||||
|
||||
rootFrame->NavigationFailed += ref new Windows::UI::Xaml::Navigation::NavigationFailedEventHandler(this, &App::OnNavigationFailed);
|
||||
|
||||
if (e->PreviousExecutionState == ApplicationExecutionState::Terminated)
|
||||
{
|
||||
// TODO: Restore the saved session state only when appropriate, scheduling the
|
||||
// final launch steps after the restore is complete
|
||||
|
||||
}
|
||||
|
||||
// Place the frame in the current Window
|
||||
Window::Current->Content = rootFrame;
|
||||
}
|
||||
|
||||
Microsoft::VisualStudio::TestPlatform::TestExecutor::WinRTCore::UnitTestClient::CreateDefaultUI();
|
||||
|
||||
Window::Current->Activate();
|
||||
|
||||
Microsoft::VisualStudio::TestPlatform::TestExecutor::WinRTCore::UnitTestClient::Run(e->Arguments);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when application execution is being suspended. Application state is saved
|
||||
/// without knowing whether the application will be terminated or resumed with the contents
|
||||
/// of memory still intact.
|
||||
/// </summary>
|
||||
/// <param name="sender">The source of the suspend request.</param>
|
||||
/// <param name="e">Details about the suspend request.</param>
|
||||
void App::OnSuspending(Object^ sender, SuspendingEventArgs^ e)
|
||||
{
|
||||
(void) sender; // Unused parameter
|
||||
(void) e; // Unused parameter
|
||||
|
||||
//TODO: Save application state and stop any background activity
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when Navigation to a certain page fails
|
||||
/// </summary>
|
||||
/// <param name="sender">The Frame which failed navigation</param>
|
||||
/// <param name="e">Details about the navigation failure</param>
|
||||
void App::OnNavigationFailed(Platform::Object ^sender, Windows::UI::Xaml::Navigation::NavigationFailedEventArgs ^e)
|
||||
{
|
||||
throw ref new FailureException("Failed to load Page " + e->SourcePageType.Name);
|
||||
}
|
||||
|
35
internal/CalculatorUnitTests/UnitTestApp.xaml.h
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
//
|
||||
// App.xaml.h
|
||||
// Declaration of the App class.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "UnitTestApp.g.h"
|
||||
#include "CalcViewModel\DateCalculatorViewModel.h"
|
||||
#include "CalcViewModel\StandardCalculatorViewModel.h"
|
||||
#include "CalcViewModel\UnitConverterViewModel.h"
|
||||
#include "CalcViewModel\MemoryItemViewModel.h"
|
||||
|
||||
namespace CalculatorUnitTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides application-specific behavior to supplement the default Application class.
|
||||
/// </summary>
|
||||
ref class App sealed
|
||||
{
|
||||
protected:
|
||||
virtual void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ e) override;
|
||||
|
||||
internal:
|
||||
App();
|
||||
|
||||
private:
|
||||
void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ e);
|
||||
void OnNavigationFailed(Platform::Object ^sender, Windows::UI::Xaml::Navigation::NavigationFailedEventArgs ^e);
|
||||
};
|
||||
}
|
||||
|
44
internal/CalculatorUnitTests/UtilsTests.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include <WexTestClass.h>
|
||||
|
||||
namespace CalculatorUnitTests
|
||||
{
|
||||
class UtilsTests
|
||||
{
|
||||
public:
|
||||
TEST_CLASS(UtilsTests);
|
||||
|
||||
TEST_METHOD(IsLastCharacterSuccess)
|
||||
{
|
||||
VERIFY_IS_TRUE(Utils::IsLastCharacterTarget(L"Test.", L'.'));
|
||||
}
|
||||
|
||||
TEST_METHOD(IsLastCharacterSuccessMultipleSuffices)
|
||||
{
|
||||
VERIFY_IS_TRUE(Utils::IsLastCharacterTarget(L"Test..", L'.'));
|
||||
}
|
||||
|
||||
TEST_METHOD(IsLastCharacterFailure)
|
||||
{
|
||||
VERIFY_IS_FALSE(Utils::IsLastCharacterTarget(L"Test", L'.'));
|
||||
}
|
||||
|
||||
TEST_METHOD(IsLastCharacterFailureAllButLastMatch)
|
||||
{
|
||||
VERIFY_IS_FALSE(Utils::IsLastCharacterTarget(L".....T", L'.'));
|
||||
}
|
||||
|
||||
TEST_METHOD(IsLastCharacterFailureEmptyInput)
|
||||
{
|
||||
VERIFY_IS_FALSE(Utils::IsLastCharacterTarget({}, L'.'));
|
||||
}
|
||||
|
||||
TEST_METHOD(IsLastCharacterFailureNullTarget)
|
||||
{
|
||||
VERIFY_IS_FALSE(Utils::IsLastCharacterTarget({}, NULL));
|
||||
}
|
||||
};
|
||||
}
|
6
internal/CalculatorUnitTests/packages.config
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.TestInfrastructure.UniversalTest" version="1.0.20181107.1" targetFramework="native" />
|
||||
<package id="Taef.Native" version="10.34.181220007" targetFramework="native" />
|
||||
<package id="Taef.Native.UWP" version="10.34.181220007" targetFramework="native" />
|
||||
</packages>
|
10
internal/CalculatorUnitTests/pch.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
//
|
||||
// pch.cpp
|
||||
// Include the standard header and generate the precompiled header.
|
||||
//
|
||||
|
||||
#include "pch.h"
|
||||
|
120
internal/CalculatorUnitTests/pch.h
Normal file
@@ -0,0 +1,120 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
//
|
||||
// pch.h
|
||||
// Header for standard system include files.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#define UNIT_TESTS
|
||||
|
||||
#include <windows.h>
|
||||
#include <collection.h>
|
||||
#include <ppltasks.h>
|
||||
#include <assert.h>
|
||||
#include <concrt.h>
|
||||
#include <string>
|
||||
#include <bitset>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <stack>
|
||||
#include <deque>
|
||||
#include <regex>
|
||||
#include <concurrent_vector.h>
|
||||
#include <experimental/resumable>
|
||||
#include <pplawait.h>
|
||||
#include <unordered_map>
|
||||
#include <mutex>
|
||||
#include <locale>
|
||||
#include <sal.h>
|
||||
#include <sstream>
|
||||
|
||||
// C++\WinRT Headers
|
||||
#include "winrt\base.h"
|
||||
#include "winrt\Windows.Foundation.Diagnostics.h"
|
||||
#include "winrt\Windows.Globalization.h"
|
||||
#include "winrt\Windows.Globalization.DateTimeFormatting.h"
|
||||
#include "winrt\Windows.System.UserProfile.h"
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace WF = Windows::Foundation;
|
||||
namespace WUC = Windows::UI::Core;
|
||||
namespace WX = Windows::UI::Xaml;
|
||||
namespace WXC = Windows::UI::Xaml::Controls;
|
||||
namespace WXCP = Windows::UI::Xaml::Controls::Primitives;
|
||||
namespace P = Platform;
|
||||
namespace PC = Platform::Collections;
|
||||
namespace WXI = Windows::UI::Xaml::Input;
|
||||
namespace WFC = Windows::Foundation::Collections;
|
||||
namespace WS = Windows::System;
|
||||
namespace WAR = Windows::ApplicationModel::Resources;
|
||||
namespace WXMA = Windows::UI::Xaml::Media::Animation;
|
||||
namespace WXD = Windows::UI::Xaml::Data;
|
||||
namespace WXInt = Windows::UI::Xaml::Interop;
|
||||
namespace WXM = Windows::UI::Xaml::Markup;
|
||||
namespace WXA = Windows::UI::Xaml::Automation;
|
||||
}
|
||||
|
||||
// The following namespaces exist as a convenience to resolve
|
||||
// ambiguity for Windows types in the Windows::UI::Xaml::Automation::Peers
|
||||
// namespace that only exist on RS3.
|
||||
// Once the app switches to min version RS3, the namespaces can be removed.
|
||||
// TODO - MSFT 12735088
|
||||
namespace StandardPeers = Windows::UI::Xaml::Automation::Peers;
|
||||
namespace CalculatorApp::Common::Automation {}
|
||||
namespace CustomPeers = CalculatorApp::Common::Automation;
|
||||
|
||||
//CalcManager Headers
|
||||
#include "CalcManager\CalculatorVector.h"
|
||||
#include "CalcManager\ExpressionCommand.h"
|
||||
#include "CalcManager\CalculatorResource.h"
|
||||
#include "CalcManager\CalculatorManager.h"
|
||||
#include "CalcManager\UnitConverter.h"
|
||||
|
||||
// CalcViewModel Headers
|
||||
#include "CalcViewModel\Common\DelegateCommand.h"
|
||||
#include "CalcViewModel\Common\Utils.h"
|
||||
#include "CalcViewModel\Common\MyVirtualKey.h"
|
||||
#include "CalcViewModel\Common\NavCategory.h"
|
||||
#include "CalcViewModel\Common\CalculatorButtonUser.h"
|
||||
#include "CalcViewModel\Common\NetworkManager.h"
|
||||
|
||||
#include "Mocks\CurrencyHttpClient.h"
|
||||
#include "Helpers.h"
|
||||
|
||||
#include "UnitTestApp.xaml.h"
|
||||
|
||||
#define TEST_METHOD_IGNORE();\
|
||||
BEGIN_TEST_METHOD_PROPERTIES()\
|
||||
TEST_METHOD_PROPERTY(L"Ignore", L"true")\
|
||||
END_TEST_METHOD_PROPERTIES()
|
||||
|
||||
#define VERIFY_THROWS_WINRT(__operation, __exception, ...) \
|
||||
{ \
|
||||
bool __exceptionHit = false; \
|
||||
try \
|
||||
{ \
|
||||
__operation; \
|
||||
} \
|
||||
catch(__exception __e) \
|
||||
{ \
|
||||
WEX::TestExecution::Private::MacroVerify::ExpectedExceptionThrown(__e, L#__exception, L#__operation, __VA_ARGS__); \
|
||||
__exceptionHit = true; \
|
||||
} \
|
||||
\
|
||||
if (!__exceptionHit) \
|
||||
{ \
|
||||
WEX::TestExecution::Private::MacroVerify::ExpectedExceptionNotThrown(L#__exception, L#__operation, PRIVATE_VERIFY_ERROR_INFO, __VA_ARGS__); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
34
internal/CalculatorUnitTests/testmd.definition
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"$schema": "http://universaltest/schema/testmddefinition-4.json",
|
||||
"Package": {
|
||||
"ComponentName": "Calculator",
|
||||
"SubComponentName": "UnitTests"
|
||||
},
|
||||
"SupportedArchitectures": [ "All" ],
|
||||
"Execution": {
|
||||
"Type": "TAEF",
|
||||
"Parameter": "/APPX:CertificateFileName=CalculatorUnitTests.cer:TrustedPeople /screenCaptureOnError /TestMode:EnsureLoggedOnUser /TestMode:EtwLogger",
|
||||
"ExecutionTimeoutInMinutes": "30"
|
||||
},
|
||||
"Dependencies": {
|
||||
"Files": [
|
||||
{
|
||||
"SourcePath": "$(AppxPackagePublicKeyFile)",
|
||||
"DestinationFolderPath": "$$(TEST_DEPLOY_BIN)"
|
||||
},
|
||||
{
|
||||
"SourcePath": "$(AppxPackageVCLibsDependency)",
|
||||
"DestinationFolderPath": "$$(TEST_DEPLOY_BIN)"
|
||||
}
|
||||
],
|
||||
"Packages": [
|
||||
"Microsoft-Windows-Test-Taef",
|
||||
"Microsoft-Windows-Test-EtwProcessor",
|
||||
"Microsoft-Test-Taef-EnsureLoggedOnUserTestMode",
|
||||
"Microsoft-Test-Taef-EtwLoggerTestMode"
|
||||
]
|
||||
},
|
||||
"Logs": [],
|
||||
"Plugins": [],
|
||||
"Profiles": []
|
||||
}
|
1
internal/Readme.txt
Normal file
@@ -0,0 +1 @@
|
||||
This directory contains projects that have dependencies on internal Microsoft tools and that are not necessary to build Calculator.
|