Merge branch 'master' into fix-code-style

This commit is contained in:
seyfer 2019-04-28 12:51:15 +02:00
commit e07f53d053
20 changed files with 1128 additions and 1071 deletions

23
.gitattributes vendored
View file

@ -12,29 +12,6 @@
############################################################################### ###############################################################################
*.cs diff=csharp *.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
*.sln merge=binary
*.csproj merge=binary
*.vbproj merge=binary
*.vcxproj merge=binary
*.vcproj merge=binary
*.dbproj merge=binary
*.fsproj merge=binary
*.lsproj merge=binary
*.wixproj merge=binary
*.modelproj merge=binary
*.sqlproj merge=binary
*.wwaproj merge=binary
############################################################################### ###############################################################################
# behavior for image files # behavior for image files
# #

1
.gitignore vendored
View file

@ -289,6 +289,7 @@ __pycache__/
# Calculator specific # Calculator specific
Generated Files/ Generated Files/
src/GraphControl/GraphingImplOverrides.props
!/build/config/TRexDefs/** !/build/config/TRexDefs/**
!src/Calculator/TemporaryKey.pfx !src/Calculator/TemporaryKey.pfx
!src/CalculatorUnitTests/CalculatorUnitTests_TemporaryKey.pfx !src/CalculatorUnitTests/CalculatorUnitTests_TemporaryKey.pfx

View file

@ -16,6 +16,9 @@ Calculator ships regularly with new features and bug fixes. You can get the late
- Calculation history and memory capabilities. - Calculation history and memory capabilities.
- Conversion between many units of measurement. - Conversion between many units of measurement.
- Currency conversion based on data retrieved from [Bing](https://www.bing.com). - Currency conversion based on data retrieved from [Bing](https://www.bing.com).
- [Infinite precision](https://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic) for basic
arithmetic operations (addition, subtraction, multiplication, division) so that calculations
never lose precision.
## Getting started ## Getting started
Prerequisites: Prerequisites:

View file

@ -1,5 +1,5 @@
<SignConfigXML> <SignConfigXML>
<job platform="" configuration="" certSubject="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" jobname="EngFunSimpleSign" approvers="gstolt;vigarg"> <job platform="" configuration="" certSubject="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" jobname="EngFunSimpleSign" approvers="">
<file src="__INPATHROOT__\Microsoft.WindowsCalculator_8wekyb3d8bbwe.appxbundle" signType="136020001" dest="__OUTPATHROOT__\Microsoft.WindowsCalculator_8wekyb3d8bbwe.appxbundle" /> <file src="__INPATHROOT__\Microsoft.WindowsCalculator_8wekyb3d8bbwe.appxbundle" signType="136020001" dest="__OUTPATHROOT__\Microsoft.WindowsCalculator_8wekyb3d8bbwe.appxbundle" />
</job> </job>
</SignConfigXML> </SignConfigXML>

View file

@ -33,6 +33,10 @@ jobs:
platform: ARM64 platform: ARM64
condition: not(eq(variables['Build.Reason'], 'PullRequest')) condition: not(eq(variables['Build.Reason'], 'PullRequest'))
- template: ./templates/run-ui-tests.yaml
parameters:
platform: x64
- template: ./templates/run-unit-tests.yaml - template: ./templates/run-unit-tests.yaml
parameters: parameters:
platform: x64 platform: x64

View file

@ -30,7 +30,7 @@ steps:
inputs: inputs:
solution: src/Calculator.sln solution: src/Calculator.sln
vsVersion: 15.0 vsVersion: 15.0
msbuildArgs: /bl:$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\Calculator.binlog /p:OutDir=$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\ /p:GenerateProjectSpecificOutputFolder=true /p:AppVersion=$(Build.BuildNumber) ${{ parameters.extraMsBuildArgs }} msbuildArgs: /bl:$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\Calculator.binlog /p:OutDir=$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\ /p:GenerateProjectSpecificOutputFolder=true /p:AppVersion=$(Build.BuildNumber) /t:Publish /p:PublishDir=$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\publish\ ${{ parameters.extraMsBuildArgs }}
platform: $(BuildPlatform) platform: $(BuildPlatform)
configuration: $(BuildConfiguration) configuration: $(BuildConfiguration)
clean: true clean: true

View file

@ -1,5 +1,5 @@
# This template contains a job which builds artifacts needed to release the app to the store and to # This template contains a job which builds artifacts needed to release the app to the store and to
# Windows using Microsoft-internal systems. It relies Microsoft-internal resources and will not # Windows using Microsoft-internal systems. It relies on Microsoft-internal resources and will not
# work outside of Microsoft. # work outside of Microsoft.
# Specifically, this job: # Specifically, this job:
# - Signs the bundle using a secure system. If you want to build your own, use SignTool following # - Signs the bundle using a secure system. If you want to build your own, use SignTool following

View file

@ -0,0 +1,52 @@
# This template contains jobs to run UI tests using WinAppDriver.
parameters:
platform: ''
jobs:
- job: UITests${{ parameters.platform }}
displayName: UITests ${{ parameters.platform }}
dependsOn: Build${{ parameters.platform }}
condition: succeeded()
pool:
vmImage: windows-2019
variables:
skipComponentGovernanceDetection: true
steps:
- checkout: none
- powershell: Set-DisplayResolution -Width 1920 -Height 1080 -Force
displayName: Set resolution to 1920x1080
continueOnError: true
- task: DownloadBuildArtifacts@0
displayName: Download AppxBundle and CalculatorUITests
inputs:
artifactName: drop
itemPattern: |
drop/Release/${{ parameters.platform }}/Calculator/AppPackages/**
drop/Release/${{ parameters.platform }}/publish/**
- task: PowerShell@2
displayName: Install certificate
inputs:
filePath: $(Build.ArtifactStagingDirectory)/drop/Release/${{ parameters.platform }}/Calculator/AppPackages/Calculator_$(Build.BuildNumber)_Test/Add-AppDevPackage.ps1
arguments: -CertificatePath $(Build.ArtifactStagingDirectory)/drop/Release/${{ parameters.platform }}/Calculator/AppPackages/Calculator_$(Build.BuildNumber)_Test/Calculator_$(Build.BuildNumber)_${{ parameters.platform }}.cer -Force
- task: PowerShell@2
displayName: Install app
inputs:
filePath: $(Build.ArtifactStagingDirectory)/drop/Release/${{ parameters.platform }}/Calculator/AppPackages/Calculator_$(Build.BuildNumber)_Test/Add-AppDevPackage.ps1
arguments: -Force
- powershell: Start-Process -FilePath "C:\Program Files (x86)\Windows Application Driver\WinAppDriver.exe" -Verb RunAs
displayName: Start WinAppDriver
- task: VSTest@2
displayName: Run CalculatorUITests
inputs:
testAssemblyVer2: $(Build.ArtifactStagingDirectory)/drop/Release/${{ parameters.platform }}/publish/CalculatorUITests.dll
vsTestVersion: 16.0
runSettingsFile: $(Build.ArtifactStagingDirectory)/drop/Release/${{ parameters.platform }}/publish/CalculatorUITests.runsettings
platform: ${{ parameters.platform }}
configuration: Release

View file

@ -153,7 +153,9 @@ The CalcEngine contains the logic for interpreting and performing operations acc
### RatPack ### RatPack
The RatPack (short for Rational Pack) is the core of the Calculator model and contains the logic for performing its mathematical operations. The interface to this layer is defined in [ratpak.h][ratpak.h]. The RatPack (short for Rational Pack) is the core of the Calculator model and contains the logic for
performing its mathematical operations (using [infinite precision][Infinite Precision] arithmetic
instead of regular floating point arithmetic). The interface to this layer is defined in [ratpak.h][ratpak.h].
[References]:#################################################################################################### [References]:####################################################################################################

View file

@ -15,11 +15,15 @@ using namespace Windows::Foundation;
using namespace Windows::System; using namespace Windows::System;
using namespace Windows::ApplicationModel::DataTransfer; using namespace Windows::ApplicationModel::DataTransfer;
unsigned long long maxOperandNumber; String^ CopyPasteManager::supportedFormats[] =
{
StandardDataFormats::Text
};
String ^ CopyPasteManager::supportedFormats[] = { StandardDataFormats::Text }; static constexpr wstring_view c_validCharacterSet{ L"0123456789()+-*/.abcdefABCDEF" };
constexpr wstring_view c_validCharacterSet{ L"0123456789()+-*/.abcdefABCDEF" }; // The below values can not be "constexpr"-ed,
// as both wstring_view and wchar[] can not be concatenated
// [\s\x85] means white-space characters // [\s\x85] means white-space characters
static const wstring c_wspc = L"[\\s\\x85]*"; static const wstring c_wspc = L"[\\s\\x85]*";
static const wstring c_wspcLParens = c_wspc + L"[(]*" + c_wspc; static const wstring c_wspcLParens = c_wspc + L"[(]*" + c_wspc;
@ -36,24 +40,41 @@ static const wstring c_binProgrammerChars = L"[0-1]+((_|'|`)[0-1]+)*";
static const wstring c_uIntSuffixes = L"[uU]?[lL]{0,2}"; static const wstring c_uIntSuffixes = L"[uU]?[lL]{0,2}";
// RegEx Patterns used by various modes // RegEx Patterns used by various modes
static const array<wregex, 1> standardModePatterns = { wregex(c_wspc + c_signedDecFloat + c_wspc) }; static const array<wregex, 1> standardModePatterns =
static const array<wregex, 2> scientificModePatterns = { wregex(L"(" + c_wspc + L"[-+]?)|(" + c_wspcLParenSigned + L")" + c_signedDecFloat + c_wspcRParens), {
wregex(L"(" + c_wspc + L"[-+]?)|(" + c_wspcLParenSigned + L")" + c_signedDecFloat wregex(c_wspc + c_signedDecFloat + c_wspc)
+ L"[e]([+]|[-])+\\d+" + c_wspcRParens) }; };
static const array<array<wregex, 5>, 4> programmerModePatterns = { static const array<wregex, 2> scientificModePatterns =
{ // Hex numbers like 5F, 4A0C, 0xa9, 0xFFull, 47CDh {
{ wregex(c_wspcLParens + L"(0[xX])?" + c_hexProgrammerChars + c_uIntSuffixes + c_wspcRParens), wregex(L"(" + c_wspc + L"[-+]?)|(" + c_wspcLParenSigned + L")" + c_signedDecFloat + c_wspcRParens),
wregex(c_wspcLParens + c_hexProgrammerChars + L"[hH]?" + c_wspcRParens) }, wregex(L"(" + c_wspc + L"[-+]?)|(" + c_wspcLParenSigned + L")" + c_signedDecFloat + L"[e]([+]|[-])+\\d+" + c_wspcRParens)
// Decimal numbers like -145, 145, 0n145, 123ull etc };
{ wregex(c_wspcLParens + L"[-+]?" + c_decProgrammerChars + L"[lL]{0,2}" + c_wspcRParens), static const array<array<wregex, 5>, 4> programmerModePatterns =
wregex(c_wspcLParens + L"(0[nN])?" + c_decProgrammerChars + c_uIntSuffixes + c_wspcRParens) }, { {
// Octal numbers like 06, 010, 0t77, 0o77, 077ull etc // Hex numbers like 5F, 4A0C, 0xa9, 0xFFull, 47CDh
{ wregex(c_wspcLParens + L"(0[otOT])?" + c_octProgrammerChars + c_uIntSuffixes + c_wspcRParens) }, {
// Binary numbers like 011010110, 0010110, 10101001, 1001b, 0b1001, 0y1001, 0b1001ull wregex(c_wspcLParens + L"(0[xX])?" + c_hexProgrammerChars + c_uIntSuffixes + c_wspcRParens),
{ wregex(c_wspcLParens + L"(0[byBY])?" + c_binProgrammerChars + c_uIntSuffixes + c_wspcRParens), wregex(c_wspcLParens + c_hexProgrammerChars + L"[hH]?" + c_wspcRParens)
wregex(c_wspcLParens + c_binProgrammerChars + L"[bB]?" + c_wspcRParens) } } },
// Decimal numbers like -145, 145, 0n145, 123ull etc
{
wregex(c_wspcLParens + L"[-+]?" + c_decProgrammerChars + L"[lL]{0,2}" +c_wspcRParens),
wregex(c_wspcLParens + L"(0[nN])?" + c_decProgrammerChars + c_uIntSuffixes + c_wspcRParens)
},
// Octal numbers like 06, 010, 0t77, 0o77, 077ull etc
{
wregex(c_wspcLParens + L"(0[otOT])?" + c_octProgrammerChars + c_uIntSuffixes + c_wspcRParens)
},
// Binary numbers like 011010110, 0010110, 10101001, 1001b, 0b1001, 0y1001, 0b1001ull
{
wregex(c_wspcLParens + L"(0[byBY])?" + c_binProgrammerChars + c_uIntSuffixes + c_wspcRParens),
wregex(c_wspcLParens + c_binProgrammerChars + L"[bB]?" + c_wspcRParens)
}
} };
static const array<wregex, 1> unitConverterPatterns =
{
wregex(c_wspc + L"[-+]?\\d*[.]?\\d*" + c_wspc)
}; };
static const array<wregex, 1> unitConverterPatterns = { wregex(c_wspc + L"[-+]?\\d*[.]?\\d*" + c_wspc) };
void CopyPasteManager::CopyToClipboard(String^ stringToCopy) void CopyPasteManager::CopyToClipboard(String^ stringToCopy)
{ {
@ -74,26 +95,25 @@ task<String ^> CopyPasteManager::GetStringToPaste(ViewMode mode, CategoryGroupTy
//-- add support to allow pasting for expressions like 1.3e12(as of now we allow 1.3e+12) //-- add support to allow pasting for expressions like 1.3e12(as of now we allow 1.3e+12)
return create_task((dataPackageView->GetTextAsync(::StandardDataFormats::Text))) return create_task((dataPackageView->GetTextAsync(::StandardDataFormats::Text)))
.then([mode, modeType, programmerNumberBase, .then([mode, modeType, programmerNumberBase, bitLengthType](String^ pastedText)
bitLengthType](String ^ pastedText) { return ValidatePasteExpression(pastedText, mode, modeType, programmerNumberBase, bitLengthType); }, {
task_continuation_context::use_arbitrary()); return ValidatePasteExpression(pastedText, mode, modeType, programmerNumberBase, bitLengthType);
}
, task_continuation_context::use_arbitrary());
} }
int CopyPasteManager::ClipboardTextFormat() int CopyPasteManager::ClipboardTextFormat()
{ {
int result = -1; const auto dataPackageView = Clipboard::GetContent();
auto dataPackageView = Clipboard::GetContent();
for (int i = 0; i < RTL_NUMBER_OF(supportedFormats); i++) for (int i = 0; i < RTL_NUMBER_OF(supportedFormats); i++)
{ {
if (dataPackageView->Contains(supportedFormats[i])) if (dataPackageView->Contains(supportedFormats[i]))
{ {
result = i; return i;
break;
} }
} }
return result; return -1;
} }
String^ CopyPasteManager::ValidatePasteExpression(String^ pastedText, ViewMode mode, int programmerNumberBase, int bitLengthType) String^ CopyPasteManager::ValidatePasteExpression(String^ pastedText, ViewMode mode, int programmerNumberBase, int bitLengthType)
@ -203,8 +223,7 @@ vector<wstring> CopyPasteManager::ExtractOperands(const wstring& pasteExpression
if ((pasteExpression.at(i) == L'+') || (pasteExpression.at(i) == L'-')) if ((pasteExpression.at(i) == L'+') || (pasteExpression.at(i) == L'-'))
{ {
// don't break the expression into operands if the encountered character corresponds to sign command(+-) // don't break the expression into operands if the encountered character corresponds to sign command(+-)
if (isPreviousOpenParen || startOfExpression || isPreviousOperator if (isPreviousOpenParen || startOfExpression || isPreviousOperator || ((mode != ViewMode::Programmer) && !((i != 0) && (pasteExpression.at(i - 1) != L'e'))))
|| ((mode != ViewMode::Programmer) && !((i != 0) && (pasteExpression.at(i - 1) != L'e'))))
{ {
isPreviousOperator = false; isPreviousOperator = false;
continue; continue;
@ -247,13 +266,8 @@ bool CopyPasteManager::ExpressionRegExMatch(vector<wstring> operands, ViewMode m
return false; return false;
} }
bool expMatched = true;
vector<wregex> patterns{}; vector<wregex> patterns{};
pair<size_t, uint64_t> operandLimits = GetMaxOperandLengthAndValue(mode, modeType, programmerNumberBase, bitLengthType);
size_t maxOperandLength = operandLimits.first;
uint64_t maxOperandValue = operandLimits.second;
if (mode == ViewMode::Standard) if (mode == ViewMode::Standard)
{ {
patterns.assign(standardModePatterns.begin(), standardModePatterns.end()); patterns.assign(standardModePatterns.begin(), standardModePatterns.end());
@ -271,11 +285,14 @@ bool CopyPasteManager::ExpressionRegExMatch(vector<wstring> operands, ViewMode m
patterns.assign(unitConverterPatterns.begin(), unitConverterPatterns.end()); patterns.assign(unitConverterPatterns.begin(), unitConverterPatterns.end());
} }
for (const wstring& operand : operands) const auto [maxOperandLength, maxOperandValue] = GetMaxOperandLengthAndValue(mode, modeType, programmerNumberBase, bitLengthType);
bool expMatched = true;
for (const auto& operand : operands)
{ {
// Each operand only needs to match one of the available patterns. // Each operand only needs to match one of the available patterns.
bool operandMatched = false; bool operandMatched = false;
for (const wregex& pattern : patterns) for (const auto& pattern : patterns)
{ {
operandMatched = operandMatched || regex_match(operand, pattern); operandMatched = operandMatched || regex_match(operand, pattern);
} }
@ -284,7 +301,7 @@ bool CopyPasteManager::ExpressionRegExMatch(vector<wstring> operands, ViewMode m
{ {
// Remove characters that are valid in the expression but we do not want to include in length calculations // Remove characters that are valid in the expression but we do not want to include in length calculations
// or which will break conversion from string-to-ULL. // or which will break conversion from string-to-ULL.
wstring operandValue = SanitizeOperand(operand); const wstring operandValue = SanitizeOperand(operand);
// If an operand exceeds the maximum length allowed, break and return. // If an operand exceeds the maximum length allowed, break and return.
if (OperandLength(operandValue, mode, modeType, programmerNumberBase) > maxOperandLength) if (OperandLength(operandValue, mode, modeType, programmerNumberBase) > maxOperandLength)
@ -320,16 +337,16 @@ bool CopyPasteManager::ExpressionRegExMatch(vector<wstring> operands, ViewMode m
pair<size_t, uint64_t> CopyPasteManager::GetMaxOperandLengthAndValue(ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, int bitLengthType) pair<size_t, uint64_t> CopyPasteManager::GetMaxOperandLengthAndValue(ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, int bitLengthType)
{ {
size_t maxLength = 0; constexpr size_t defaultMaxOperandLength = 0;
uint64_t maxValue = 0; constexpr uint64_t defaultMaxValue = 0;
if (mode == ViewMode::Standard) if (mode == ViewMode::Standard)
{ {
maxLength = MaxStandardOperandLength; return make_pair(MaxStandardOperandLength, defaultMaxValue);
} }
else if (mode == ViewMode::Scientific) else if (mode == ViewMode::Scientific)
{ {
maxLength = MaxScientificOperandLength; return make_pair(MaxScientificOperandLength, defaultMaxValue);
} }
else if (mode == ViewMode::Programmer) else if (mode == ViewMode::Programmer)
{ {
@ -369,15 +386,17 @@ pair<size_t, uint64_t> CopyPasteManager::GetMaxOperandLengthAndValue(ViewMode mo
unsigned int signBit = (programmerNumberBase == DecBase) ? 1 : 0; unsigned int signBit = (programmerNumberBase == DecBase) ? 1 : 0;
maxLength = (size_t)ceil((bitLength - signBit) / bitsPerDigit); const auto maxLength = static_cast<size_t>(ceil((bitLength - signBit) / bitsPerDigit));
maxValue = UINT64_MAX >> (MaxProgrammerBitLength - (bitLength - signBit)); const uint64_t maxValue = UINT64_MAX >> (MaxProgrammerBitLength - (bitLength - signBit));
return make_pair(maxLength, maxValue);
} }
else if (modeType == CategoryGroupType::Converter) else if (modeType == CategoryGroupType::Converter)
{ {
maxLength = MaxConverterInputLength; return make_pair(MaxConverterInputLength, defaultMaxValue);
} }
return make_pair(maxLength, maxValue); return make_pair(defaultMaxOperandLength, defaultMaxValue);
} }
wstring CopyPasteManager::SanitizeOperand(const wstring& operand) wstring CopyPasteManager::SanitizeOperand(const wstring& operand)
@ -396,8 +415,7 @@ bool CopyPasteManager::TryOperandToULL(const wstring& operand, int numberBase, u
return false; return false;
} }
// Default to base10 int intBase;
int intBase = 10;
switch (numberBase) switch (numberBase)
{ {
case HexBase: case HexBase:
@ -409,6 +427,7 @@ bool CopyPasteManager::TryOperandToULL(const wstring& operand, int numberBase, u
case BinBase: case BinBase:
intBase = 2; intBase = 2;
break; break;
default:
case DecBase: case DecBase:
intBase = 10; intBase = 10;
break; break;
@ -420,11 +439,11 @@ bool CopyPasteManager::TryOperandToULL(const wstring& operand, int numberBase, u
result = stoull(operand, &size, intBase); result = stoull(operand, &size, intBase);
return true; return true;
} }
catch (invalid_argument) catch (const invalid_argument&)
{ {
// Do nothing // Do nothing
} }
catch (out_of_range) catch (const out_of_range&)
{ {
// Do nothing // Do nothing
} }
@ -432,35 +451,28 @@ bool CopyPasteManager::TryOperandToULL(const wstring& operand, int numberBase, u
return false; return false;
} }
size_t CopyPasteManager::OperandLength(wstring operand, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase) size_t CopyPasteManager::OperandLength(const wstring& operand, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase)
{ {
size_t len = 0; if (modeType == CategoryGroupType::Converter) {
if (mode == ViewMode::Standard || mode == ViewMode::Scientific) return operand.length();
{
len = StandardScientificOperandLength(operand);
}
else if (mode == ViewMode::Programmer)
{
len = ProgrammerOperandLength(operand, programmerNumberBase);
}
else if (modeType == CategoryGroupType::Converter)
{
len = operand.length();
} }
return len; switch(mode) {
case ViewMode::Standard:
case ViewMode::Scientific:
return StandardScientificOperandLength(operand);
case ViewMode::Programmer:
return ProgrammerOperandLength(operand, programmerNumberBase);
default:
return 0;
}
} }
size_t CopyPasteManager::StandardScientificOperandLength(wstring operand) size_t CopyPasteManager::StandardScientificOperandLength(const wstring& operand)
{ {
bool hasDecimal = false; const bool hasDecimal = operand.find('.') != wstring::npos;
for (size_t i = 0; i < operand.length(); i++)
{
if (operand[i] == L'.')
{
hasDecimal = true;
}
}
if (hasDecimal) if (hasDecimal)
{ {
@ -482,7 +494,6 @@ size_t CopyPasteManager::StandardScientificOperandLength(wstring operand)
size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int numberBase) size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int numberBase)
{ {
size_t len = operand.length();
vector<wstring> prefixes{}; vector<wstring> prefixes{};
vector<wstring> suffixes{}; vector<wstring> suffixes{};
@ -504,7 +515,7 @@ size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int num
break; break;
default: default:
// No defined prefixes/suffixes // No defined prefixes/suffixes
break; return 0;
} }
// UInt suffixes are common across all modes // UInt suffixes are common across all modes
@ -514,9 +525,11 @@ size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int num
wstring operandUpper = operand; wstring operandUpper = operand;
transform(operandUpper.begin(), operandUpper.end(), operandUpper.begin(), towupper); transform(operandUpper.begin(), operandUpper.end(), operandUpper.begin(), towupper);
size_t len = operand.length();
// Detect if there is a suffix and subtract its length // Detect if there is a suffix and subtract its length
// Check suffixes first to allow e.g. "0b" to result in length 1 (value 0), rather than length 0 (no value). // Check suffixes first to allow e.g. "0b" to result in length 1 (value 0), rather than length 0 (no value).
for (const wstring& suffix : suffixes) for (const auto& suffix : suffixes)
{ {
if (len < suffix.length()) if (len < suffix.length())
{ {
@ -531,7 +544,7 @@ size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int num
} }
// Detect if there is a prefix and subtract its length // Detect if there is a prefix and subtract its length
for (const wstring& prefix : prefixes) for (const auto& prefix : prefixes)
{ {
if (len < prefix.length()) if (len < prefix.length())
{ {

View file

@ -13,21 +13,20 @@ namespace CalculatorUnitTests
namespace CalculatorApp namespace CalculatorApp
{ {
#define QwordType 1 inline constexpr auto QwordType = 1;
#define DwordType 2 inline constexpr auto DwordType = 2;
#define WordType 3 inline constexpr auto WordType = 3;
#define ByteType 4 inline constexpr auto ByteType = 4;
#define HexBase 5 inline constexpr auto HexBase = 5;
#define DecBase 6 inline constexpr auto DecBase = 6;
#define OctBase 7 inline constexpr auto OctBase = 7;
#define BinBase 8 inline constexpr auto BinBase = 8;
class CopyPasteManager class CopyPasteManager
{ {
public: public:
static void CopyToClipboard(Platform::String^ stringToCopy); static void CopyToClipboard(Platform::String^ stringToCopy);
static concurrency::task<Platform::String ^> GetStringToPaste(CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, static concurrency::task<Platform::String^> GetStringToPaste(CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, int programmerNumberBase = -1, int bitLengthType = -1);
int programmerNumberBase = -1, int bitLengthType = -1);
static bool HasStringToPaste() static bool HasStringToPaste()
{ {
return ClipboardTextFormat() >= 0; return ClipboardTextFormat() >= 0;
@ -37,24 +36,26 @@ namespace CalculatorApp
private: private:
static int ClipboardTextFormat(); static int ClipboardTextFormat();
static Platform::String static Platform::String^ ValidatePasteExpression(
^ ValidatePasteExpression(Platform::String ^ pastedText, CalculatorApp::Common::ViewMode mode, int programmerNumberBase, int bitLengthType); Platform::String^ pastedText,
static Platform::String CalculatorApp::Common::ViewMode mode,
^ ValidatePasteExpression(Platform::String ^ pastedText, CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, int programmerNumberBase,
int programmerNumberBase, int bitLengthType); int bitLengthType);
static Platform::String^ ValidatePasteExpression(
Platform::String^ pastedText,
CalculatorApp::Common::ViewMode mode,
CalculatorApp::Common::CategoryGroupType modeType,
int programmerNumberBase,
int bitLengthType);
static std::vector<std::wstring> ExtractOperands(const std::wstring& pasteExpression, CalculatorApp::Common::ViewMode mode, static std::vector<std::wstring> ExtractOperands(const std::wstring& pasteExpression, CalculatorApp::Common::ViewMode mode, int programmerNumberBase = -1, int bitLengthType = -1);
int programmerNumberBase = -1, int bitLengthType = -1); static bool ExpressionRegExMatch(std::vector<std::wstring> operands, CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, int programmerNumberBase = -1, int bitLengthType = -1);
static bool ExpressionRegExMatch(std::vector<std::wstring> operands, CalculatorApp::Common::ViewMode mode,
CalculatorApp::Common::CategoryGroupType modeType, int programmerNumberBase = -1, int bitLengthType = -1);
static std::pair<size_t, uint64_t> GetMaxOperandLengthAndValue(CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, static std::pair<size_t, uint64_t> GetMaxOperandLengthAndValue(CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, int programmerNumberBase = -1, int bitLengthType = -1);
int programmerNumberBase = -1, int bitLengthType = -1);
static std::wstring SanitizeOperand(const std::wstring& operand); static std::wstring SanitizeOperand(const std::wstring& operand);
static bool TryOperandToULL(const std::wstring& operand, int numberBase, unsigned long long int& result); static bool TryOperandToULL(const std::wstring& operand, int numberBase, unsigned long long int& result);
static size_t OperandLength(std::wstring operand, CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, static size_t OperandLength(const std::wstring& operand, CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, int programmerNumberBase = -1);
int programmerNumberBase = -1); static size_t StandardScientificOperandLength(const std::wstring& operand);
static size_t StandardScientificOperandLength(std::wstring operand);
static size_t ProgrammerOperandLength(const std::wstring& operand, int numberBase); static size_t ProgrammerOperandLength(const std::wstring& operand, int numberBase);
static std::wstring RemoveUnwantedCharsFromWstring(const std::wstring& input); static std::wstring RemoveUnwantedCharsFromWstring(const std::wstring& input);

View file

@ -20,13 +20,27 @@ DateCalculationEngine::DateCalculationEngine(_In_ String ^ calendarIdentifier)
// Returns: True if function succeeds to calculate the date else returns False // Returns: True if function succeeds to calculate the date else returns False
bool DateCalculationEngine::AddDuration(_In_ DateTime startDate, _In_ const DateDifference& duration, _Out_ DateTime* endDate) bool DateCalculationEngine::AddDuration(_In_ DateTime startDate, _In_ const DateDifference& duration, _Out_ DateTime* endDate)
{ {
auto currentCalendarSystem = m_calendar->GetCalendarSystem();
try try
{ {
m_calendar->SetDateTime(startDate); m_calendar->SetDateTime(startDate);
if (duration.year != 0) if (duration.year != 0)
{ {
// The Japanese Era system can have multiple year partitions within the same year.
// For example, April 30, 2019 is denoted April 30, Heisei 31; May 1, 2019 is denoted as May 1, Reiwa 1.
// The Calendar treats Heisei 31 and Reiwa 1 as separate years, which results in some unexpected behaviors where subtracting a year from Reiwa 1 results in a date in Heisei 31.
// To provide the expected result across era boundaries, we first convert the Japanese era system to a Gregorian system, do date math, and then convert back to the Japanese era system.
// This works because the Japanese era system maintains the same year/month boundaries and durations as the Gregorian system and is only different in display value.
if (currentCalendarSystem == CalendarIdentifiers::Japanese)
{
m_calendar->ChangeCalendarSystem(CalendarIdentifiers::Gregorian);
}
m_calendar->AddYears(duration.year); m_calendar->AddYears(duration.year);
m_calendar->ChangeCalendarSystem(currentCalendarSystem);
} }
if (duration.month != 0) if (duration.month != 0)
{ {
@ -41,6 +55,9 @@ bool DateCalculationEngine::AddDuration(_In_ DateTime startDate, _In_ const Date
} }
catch (Platform::InvalidArgumentException ^ ex) catch (Platform::InvalidArgumentException ^ ex)
{ {
// ensure that we revert to the correct calendar system
m_calendar->ChangeCalendarSystem(currentCalendarSystem);
// Do nothing // Do nothing
return false; return false;
} }
@ -52,6 +69,8 @@ bool DateCalculationEngine::AddDuration(_In_ DateTime startDate, _In_ const Date
// Returns: True if function succeeds to calculate the date else returns False // Returns: True if function succeeds to calculate the date else returns False
bool DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ const DateDifference& duration, _Out_ DateTime* endDate) bool DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ const DateDifference& duration, _Out_ DateTime* endDate)
{ {
auto currentCalendarSystem = m_calendar->GetCalendarSystem();
// For Subtract the Algorithm is different than Add. Here the smaller units are subtracted first // For Subtract the Algorithm is different than Add. Here the smaller units are subtracted first
// and then the larger units. // and then the larger units.
try try
@ -68,13 +87,28 @@ bool DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ const
} }
if (duration.year != 0) if (duration.year != 0)
{ {
// The Japanese Era system can have multiple year partitions within the same year.
// For example, April 30, 2019 is denoted April 30, Heisei 31; May 1, 2019 is denoted as May 1, Reiwa 1.
// The Calendar treats Heisei 31 and Reiwa 1 as separate years, which results in some unexpected behaviors where subtracting a year from Reiwa 1 results in a date in Heisei 31.
// To provide the expected result across era boundaries, we first convert the Japanese era system to a Gregorian system, do date math, and then convert back to the Japanese era system.
// This works because the Japanese era system maintains the same year/month boundaries and durations as the Gregorian system and is only different in display value.
if (currentCalendarSystem == CalendarIdentifiers::Japanese)
{
m_calendar->ChangeCalendarSystem(CalendarIdentifiers::Gregorian);
}
m_calendar->AddYears(-duration.year); m_calendar->AddYears(-duration.year);
m_calendar->ChangeCalendarSystem(currentCalendarSystem);
} }
*endDate = m_calendar->GetDateTime(); *endDate = m_calendar->GetDateTime();
} }
catch (Platform::InvalidArgumentException ^ ex) catch (Platform::InvalidArgumentException ^ ex)
{ {
// ensure that we revert to the correct calendar system
m_calendar->ChangeCalendarSystem(currentCalendarSystem);
// Do nothing // Do nothing
return false; return false;
} }

View file

@ -782,6 +782,12 @@ void StandardCalculatorViewModel::OnPaste(String ^ pastedString, ViewMode mode)
NumbersAndOperatorsEnum mappedNumOp = MapCharacterToButtonId(*it, canSendNegate); NumbersAndOperatorsEnum mappedNumOp = MapCharacterToButtonId(*it, canSendNegate);
if (mappedNumOp == NumbersAndOperatorsEnum::None)
{
++it;
continue;
}
if (isFirstLegalChar || isPreviousOperator) if (isFirstLegalChar || isPreviousOperator)
{ {
isFirstLegalChar = false; isFirstLegalChar = false;
@ -803,8 +809,6 @@ void StandardCalculatorViewModel::OnPaste(String ^ pastedString, ViewMode mode)
} }
} }
if (mappedNumOp != NumbersAndOperatorsEnum::None)
{
switch (mappedNumOp) switch (mappedNumOp)
{ {
// Opening parenthesis starts a new expression and pushes negation state onto the stack // Opening parenthesis starts a new expression and pushes negation state onto the stack
@ -873,7 +877,6 @@ void StandardCalculatorViewModel::OnPaste(String ^ pastedString, ViewMode mode)
} }
} }
} }
}
// Handle exponent and exponent sign (...e+... or ...e-...) // Handle exponent and exponent sign (...e+... or ...e-...)
if (mappedNumOp == NumbersAndOperatorsEnum::Exp) if (mappedNumOp == NumbersAndOperatorsEnum::Exp)

View file

@ -18,6 +18,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalcViewModel", "CalcViewMo
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalculatorUnitTests", "CalculatorUnitTests\CalculatorUnitTests.vcxproj", "{D3BAED2C-4B07-4E1D-8807-9D6499450349}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalculatorUnitTests", "CalculatorUnitTests\CalculatorUnitTests.vcxproj", "{D3BAED2C-4B07-4E1D-8807-9D6499450349}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CalculatorUITests", "CalculatorUITests\CalculatorUITests.csproj", "{B2C5ADFF-D6B5-48C1-BB8C-571BFD583D7F}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM Debug|ARM = Debug|ARM
@ -102,6 +104,22 @@ Global
{D3BAED2C-4B07-4E1D-8807-9D6499450349}.Release|x86.ActiveCfg = Release|Win32 {D3BAED2C-4B07-4E1D-8807-9D6499450349}.Release|x86.ActiveCfg = Release|Win32
{D3BAED2C-4B07-4E1D-8807-9D6499450349}.Release|x86.Build.0 = Release|Win32 {D3BAED2C-4B07-4E1D-8807-9D6499450349}.Release|x86.Build.0 = Release|Win32
{D3BAED2C-4B07-4E1D-8807-9D6499450349}.Release|x86.Deploy.0 = Release|Win32 {D3BAED2C-4B07-4E1D-8807-9D6499450349}.Release|x86.Deploy.0 = Release|Win32
{B2C5ADFF-D6B5-48C1-BB8C-571BFD583D7F}.Debug|ARM.ActiveCfg = Debug|Any CPU
{B2C5ADFF-D6B5-48C1-BB8C-571BFD583D7F}.Debug|ARM.Build.0 = Debug|Any CPU
{B2C5ADFF-D6B5-48C1-BB8C-571BFD583D7F}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{B2C5ADFF-D6B5-48C1-BB8C-571BFD583D7F}.Debug|ARM64.Build.0 = Debug|Any CPU
{B2C5ADFF-D6B5-48C1-BB8C-571BFD583D7F}.Debug|x64.ActiveCfg = Debug|Any CPU
{B2C5ADFF-D6B5-48C1-BB8C-571BFD583D7F}.Debug|x64.Build.0 = Debug|Any CPU
{B2C5ADFF-D6B5-48C1-BB8C-571BFD583D7F}.Debug|x86.ActiveCfg = Debug|Any CPU
{B2C5ADFF-D6B5-48C1-BB8C-571BFD583D7F}.Debug|x86.Build.0 = Debug|Any CPU
{B2C5ADFF-D6B5-48C1-BB8C-571BFD583D7F}.Release|ARM.ActiveCfg = Release|Any CPU
{B2C5ADFF-D6B5-48C1-BB8C-571BFD583D7F}.Release|ARM.Build.0 = Release|Any CPU
{B2C5ADFF-D6B5-48C1-BB8C-571BFD583D7F}.Release|ARM64.ActiveCfg = Release|Any CPU
{B2C5ADFF-D6B5-48C1-BB8C-571BFD583D7F}.Release|ARM64.Build.0 = Release|Any CPU
{B2C5ADFF-D6B5-48C1-BB8C-571BFD583D7F}.Release|x64.ActiveCfg = Release|Any CPU
{B2C5ADFF-D6B5-48C1-BB8C-571BFD583D7F}.Release|x64.Build.0 = Release|Any CPU
{B2C5ADFF-D6B5-48C1-BB8C-571BFD583D7F}.Release|x86.ActiveCfg = Release|Any CPU
{B2C5ADFF-D6B5-48C1-BB8C-571BFD583D7F}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View file

@ -615,8 +615,7 @@
x:Uid="RefreshButtonText" x:Uid="RefreshButtonText"
Foreground="{ThemeResource SystemControlHyperlinkBaseHighBrush}" Foreground="{ThemeResource SystemControlHyperlinkBaseHighBrush}"
Click="CurrencyRefreshButton_Click"/> Click="CurrencyRefreshButton_Click"/>
<TextBlock Margin="0,7,0,0" Style="{ThemeResource CaptionTextBlockStyle}"> <TextBlock Margin="3,7,0,0" Style="{ThemeResource CaptionTextBlockStyle}">
<Run x:Name="Spacing" Text="&#x200A;"/>
<Run x:Name="CurrencySecondaryStatus" <Run x:Name="CurrencySecondaryStatus"
FontWeight="SemiBold" FontWeight="SemiBold"
Text=""/> Text=""/>

View file

@ -0,0 +1,44 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Windows;
using System;
namespace CalculatorUITests
{
public class CalculatorSession
{
// Note: append /wd/hub to the URL if you're directing the test at Appium
private const string WindowsApplicationDriverUrl = "http://127.0.0.1:4723";
private const string CalculatorAppId = "Microsoft.WindowsCalculator.Dev_8wekyb3d8bbwe!App";
protected static WindowsDriver<WindowsElement> session;
public static void Setup(TestContext context)
{
// Launch Calculator application if it is not yet launched
if (session == null)
{
// Create a new session to bring up an instance of the Calculator application
// Note: Multiple calculator windows (instances) share the same process Id
var options = new AppiumOptions();
options.AddAdditionalCapability("app", CalculatorAppId);
options.AddAdditionalCapability("deviceName", "WindowsPC");
session = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), options);
session.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(180);
Assert.IsNotNull(session);
}
}
public static void TearDown()
{
// Close the application and delete the session
if (session != null)
{
session.Quit();
session = null;
}
}
}
}

View file

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" />
<PackageReference Include="Appium.WebDriver" Version="4.0.0.6-beta" />
</ItemGroup>
<ItemGroup>
<None Update="CalculatorUITests.runsettings">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<DataCollectionRunSettings>
<DataCollectors>
<DataCollector uri="datacollector://microsoft/VideoRecorder/1.0" assemblyQualifiedName="Microsoft.VisualStudio.TestTools.DataCollection.VideoRecorder.VideoRecorderDataCollector, Microsoft.VisualStudio.TestTools.DataCollection.VideoRecorder, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" friendlyName="Screen and Voice Recorder">
</DataCollector>
</DataCollectors>
</DataCollectionRunSettings>
</RunSettings>

View file

@ -0,0 +1,112 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium.Appium.Windows;
using System.Threading;
using System;
namespace CalculatorUITests
{
[TestClass]
public class StandardModeTests : CalculatorSession
{
private static WindowsElement header;
private static WindowsElement calculatorResult;
[TestMethod]
public void Addition()
{
// Find the buttons by their names and click them in sequence to perform 1 + 7 = 8
session.FindElementByName("One").Click();
session.FindElementByName("Plus").Click();
session.FindElementByName("Seven").Click();
session.FindElementByName("Equals").Click();
Assert.AreEqual("8", GetCalculatorResultText());
}
[TestMethod]
public void Division()
{
// Find the buttons by their accessibility ids and click them in sequence to perform 88 / 11 = 8
session.FindElementByAccessibilityId("num8Button").Click();
session.FindElementByAccessibilityId("num8Button").Click();
session.FindElementByAccessibilityId("divideButton").Click();
session.FindElementByAccessibilityId("num1Button").Click();
session.FindElementByAccessibilityId("num1Button").Click();
session.FindElementByAccessibilityId("equalButton").Click();
Assert.AreEqual("8", GetCalculatorResultText());
}
[TestMethod]
public void Multiplication()
{
session.FindElementByAccessibilityId("num9Button").Click();
session.FindElementByAccessibilityId("multiplyButton").Click();
session.FindElementByAccessibilityId("num9Button").Click();
session.FindElementByAccessibilityId("equalButton").Click();
Assert.AreEqual("81", GetCalculatorResultText());
}
[TestMethod]
public void Subtraction()
{
// Find the buttons by their accessibility ids using XPath and click them in sequence to perform 9 - 1 = 8
session.FindElementByAccessibilityId("num9Button").Click();
session.FindElementByAccessibilityId("minusButton").Click();
session.FindElementByAccessibilityId("num1Button").Click();
session.FindElementByAccessibilityId("equalButton").Click();
Assert.AreEqual("8", GetCalculatorResultText());
}
[ClassInitialize]
public static void ClassInitialize(TestContext context)
{
// Create session to launch a Calculator window
Setup(context);
// Identify calculator mode by locating the header
try
{
header = session.FindElementByAccessibilityId("Header");
}
catch
{
header = session.FindElementByAccessibilityId("ContentPresenter");
}
// Ensure that calculator is in standard mode
if (!header.Text.Equals("Standard", StringComparison.OrdinalIgnoreCase))
{
session.FindElementByAccessibilityId("TogglePaneButton").Click();
Thread.Sleep(TimeSpan.FromSeconds(1));
var splitViewPane = session.FindElementByClassName("SplitViewPane");
splitViewPane.FindElementByName("Standard Calculator").Click();
Thread.Sleep(TimeSpan.FromSeconds(1));
Assert.IsTrue(header.Text.Equals("Standard", StringComparison.OrdinalIgnoreCase));
}
// Locate the calculatorResult element
calculatorResult = session.FindElementByAccessibilityId("CalculatorResults");
Assert.IsNotNull(calculatorResult);
}
[ClassCleanup]
public static void ClassCleanup()
{
TearDown();
}
[TestInitialize]
public void Clear()
{
session.FindElementByName("Clear").Click();
Assert.AreEqual("0", GetCalculatorResultText());
}
private string GetCalculatorResultText()
{
return calculatorResult.Text.Replace("Display is", string.Empty).Trim();
}
}
}

View file

@ -44,226 +44,83 @@ namespace DateCalculationUnitTests
DateTimeTestCase datetimeAddCase[c_addCases]; DateTimeTestCase datetimeAddCase[c_addCases];
DateTimeTestCase datetimeSubtractCase[c_subtractCases]; DateTimeTestCase datetimeSubtractCase[c_subtractCases];
// Test Class // Test Class
TEST_CLASS(DateCalculatorUnitTests){ public: TEST_CLASS_INITIALIZE(TestClassSetup){ /* Test Case Data */ TEST_CLASS(DateCalculatorUnitTests)
{
public:
TEST_CLASS_INITIALIZE(TestClassSetup)
{
/* Test Case Data */
// Dates - DD.MM.YYYY // Dates - DD.MM.YYYY
/*31.12.9999*/ date[0].wYear = 9999; /*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;
date[0].wMonth = 12; /*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;
date[0].wDayOfWeek = 5; /*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;
date[0].wDay = 31; /*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;
date[0].wHour = 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;
date[0].wMinute = 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;
date[0].wSecond = 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;
date[0].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;
/*30.12.9999*/ date[1].wYear = 9999; /*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;
date[1].wMonth = 12; /*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;
date[1].wDayOfWeek = 4; /*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;
date[1].wDay = 30; /*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;
date[1].wHour = 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;
date[1].wMinute = 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;
date[1].wSecond = 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[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 // Date Differences
dateDifference[0].year = 1; dateDifference[0].year = 1; dateDifference[0].month = 1;
dateDifference[0].month = 1; dateDifference[1].month = 1; dateDifference[1].day = 10;
dateDifference[1].month = 1;
dateDifference[1].day = 10;
dateDifference[2].day = 2; dateDifference[2].day = 2;
/*date[2]-[0]*/ dateDifference[3].week = 52; /*date[2]-[0]*/ dateDifference[3].week = 52; dateDifference[3].day = 1;
dateDifference[3].day = 1;
/*date[2]-[0]*/ dateDifference[4].year = 1; /*date[2]-[0]*/ dateDifference[4].year = 1;
dateDifference[5].day = 365; dateDifference[5].day = 365;
dateDifference[6].month = 1; dateDifference[6].month = 1;
dateDifference[7].month = 1; dateDifference[7].month = 1; dateDifference[7].day = 2;
dateDifference[7].day = 2;
dateDifference[8].day = 31; dateDifference[8].day = 31;
dateDifference[9].month = 11; dateDifference[9].month = 11; dateDifference[9].day = 1;
dateDifference[9].day = 1; dateDifference[10].year = 8398; dateDifference[10].month = 11; dateDifference[10].day = 30;
dateDifference[10].year = 8398;
dateDifference[10].month = 11;
dateDifference[10].day = 30;
dateDifference[11].year = 2008; dateDifference[11].year = 2008;
dateDifference[12].year = 7991; dateDifference[12].year = 7991; dateDifference[12].month = 11;
dateDifference[12].month = 11; dateDifference[13].week = 416998; dateDifference[13].day = 1;
dateDifference[13].week = 416998;
dateDifference[13].day = 1;
/* Test Cases */ /* Test Cases */
// Date Difference test cases // Date Difference test cases
datetimeDifftest[0].startDate = date[0]; datetimeDifftest[0].startDate = date[0]; datetimeDifftest[0].endDate = date[3]; datetimeDifftest[0].dateDiff = dateDifference[10];
datetimeDifftest[0].endDate = date[3]; datetimeDifftest[1].startDate = date[0]; datetimeDifftest[1].endDate = date[2]; datetimeDifftest[1].dateDiff = dateDifference[5];
datetimeDifftest[0].dateDiff = dateDifference[10]; datetimeDifftest[2].startDate = date[0]; datetimeDifftest[2].endDate = date[2]; datetimeDifftest[2].dateDiff = dateDifference[4];
datetimeDifftest[1].startDate = date[0]; datetimeDifftest[3].startDate = date[0]; datetimeDifftest[3].endDate = date[2]; datetimeDifftest[3].dateDiff = dateDifference[3];
datetimeDifftest[1].endDate = date[2]; datetimeDifftest[4].startDate = date[14]; datetimeDifftest[4].endDate = date[7]; datetimeDifftest[4].dateDiff = dateDifference[7];
datetimeDifftest[1].dateDiff = dateDifference[5]; datetimeDifftest[5].startDate = date[14]; datetimeDifftest[5].endDate = date[7]; datetimeDifftest[5].dateDiff = dateDifference[8];
datetimeDifftest[2].startDate = date[0]; datetimeDifftest[6].startDate = date[11]; datetimeDifftest[6].endDate = date[8]; datetimeDifftest[6].dateDiff = dateDifference[9];
datetimeDifftest[2].endDate = date[2]; datetimeDifftest[7].startDate = date[13]; datetimeDifftest[7].endDate = date[0]; datetimeDifftest[7].dateDiff = dateDifference[12];
datetimeDifftest[2].dateDiff = dateDifference[4]; datetimeDifftest[8].startDate = date[13]; datetimeDifftest[8].endDate = date[0]; datetimeDifftest[8].dateDiff = dateDifference[13];
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) // Date Add Out of Bound test cases (Negative tests)
/*OutofBound*/ datetimeBoundAdd[0].startDate = date[1]; /*OutofBound*/ datetimeBoundAdd[0].startDate = date[1]; datetimeBoundAdd[0].endDate = date[0]; datetimeBoundAdd[0].dateDiff = dateDifference[2]; // on Add date[0] not used
datetimeBoundAdd[0].endDate = date[0]; /*OutofBound*/ datetimeBoundAdd[1].startDate = date[2]; datetimeBoundAdd[1].endDate = date[0]; datetimeBoundAdd[1].dateDiff = dateDifference[11]; // on Add date[0] not used
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) // Date Subtract Out of Bound test cases (Negative tests)
/*OutofBound*/ datetimeBoundSubtract[0].startDate = date[3]; /*OutofBound*/ datetimeBoundSubtract[0].startDate = date[3]; datetimeBoundSubtract[0].endDate = date[0]; datetimeBoundSubtract[0].dateDiff = dateDifference[2]; // on subtract date[0] not used
datetimeBoundSubtract[0].endDate = date[0]; /*OutofBound*/ datetimeBoundSubtract[1].startDate = date[14]; datetimeBoundSubtract[1].endDate = date[0]; datetimeBoundSubtract[1].dateDiff = dateDifference[11]; // on subtract date[0] not used
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) // Date Add test cases (Positive tests)
datetimeAddCase[0].startDate = date[13]; datetimeAddCase[0].startDate = date[13]; datetimeAddCase[0].endDate = date[7]; datetimeAddCase[0].dateDiff = dateDifference[6];// add
datetimeAddCase[0].endDate = date[7]; datetimeAddCase[1].startDate = date[14]; datetimeAddCase[1].endDate = date[5]; datetimeAddCase[1].dateDiff = dateDifference[1];// add
datetimeAddCase[0].dateDiff = dateDifference[6]; // add datetimeAddCase[2].startDate = date[13]; datetimeAddCase[2].endDate = date[6]; datetimeAddCase[2].dateDiff = dateDifference[1];// 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) // Date Subtract test cases (Positive tests)
datetimeSubtractCase[0].startDate = date[14]; datetimeSubtractCase[0].startDate = date[14]; datetimeSubtractCase[0].endDate = date[7]; datetimeSubtractCase[0].dateDiff = dateDifference[6];// subtract
datetimeSubtractCase[0].endDate = date[7]; datetimeSubtractCase[1].startDate = date[6]; datetimeSubtractCase[1].endDate = date[11]; datetimeSubtractCase[1].dateDiff = dateDifference[1];// subtract
datetimeSubtractCase[0].dateDiff = dateDifference[6]; // subtract datetimeSubtractCase[2].startDate = date[9]; datetimeSubtractCase[2].endDate = date[12]; datetimeSubtractCase[2].dateDiff = dateDifference[1];// 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
} }
/* Duration Between Two Date Tests -- Timediff obtained after calculation should be checked to be identical */ /* Duration Between Two Date Tests -- Timediff obtained after calculation should be checked to be identical */
TEST_METHOD(TestDateDiff) TEST_METHOD(TestDateDiff)
{ {
@ -300,8 +157,7 @@ TEST_METHOD(TestDateDiff)
// } // }
// // Calculate the difference // // Calculate the difference
// m_DateCalcEngine.GetDateDifference(DateUtils::SystemTimeToDateTime(datetimeDifftest[testIndex].startDate), // m_DateCalcEngine.GetDateDifference(DateUtils::SystemTimeToDateTime(datetimeDifftest[testIndex].startDate), DateUtils::SystemTimeToDateTime(datetimeDifftest[testIndex].endDate), dateOutputFormat, &diff);
// DateUtils::SystemTimeToDateTime(datetimeDifftest[testIndex].endDate), dateOutputFormat, &diff);
// // Assert for the result // // Assert for the result
// bool areIdentical = true; // bool areIdentical = true;
@ -327,8 +183,7 @@ TEST_METHOD(TestAddOob)
// DateTime endDate; // DateTime endDate;
// // Add Duration // // Add Duration
// bool isValid = m_DateCalcEngine.AddDuration(DateUtils::SystemTimeToDateTime(datetimeBoundAdd[testIndex].startDate), // bool isValid = m_DateCalcEngine.AddDuration(DateUtils::SystemTimeToDateTime(datetimeBoundAdd[testIndex].startDate), datetimeBoundAdd[testIndex].dateDiff, &endDate);
// datetimeBoundAdd[testIndex].dateDiff, &endDate);
// // Assert for the result // // Assert for the result
// VERIFY_IS_FALSE(isValid); // VERIFY_IS_FALSE(isValid);
@ -343,8 +198,7 @@ TEST_METHOD(TestSubtractOob)
DateTime endDate; DateTime endDate;
// Subtract Duration // Subtract Duration
bool isValid = m_DateCalcEngine.SubtractDuration(DateUtils::SystemTimeToDateTime(datetimeBoundSubtract[testIndex].startDate), bool isValid = m_DateCalcEngine.SubtractDuration(DateUtils::SystemTimeToDateTime(datetimeBoundSubtract[testIndex].startDate), datetimeBoundSubtract[testIndex].dateDiff, &endDate);
datetimeBoundSubtract[testIndex].dateDiff, &endDate);
// Assert for the result // Assert for the result
VERIFY_IS_FALSE(isValid); VERIFY_IS_FALSE(isValid);
@ -361,8 +215,7 @@ TEST_METHOD(TestAddition)
// DateTime endDate; // DateTime endDate;
// // Add Duration // // Add Duration
// bool isValid = m_DateCalcEngine.AddDuration(DateUtils::SystemTimeToDateTime(datetimeAddCase[testIndex].startDate), // bool isValid = m_DateCalcEngine.AddDuration(DateUtils::SystemTimeToDateTime(datetimeAddCase[testIndex].startDate), datetimeAddCase[testIndex].dateDiff, &endDate);
// datetimeAddCase[testIndex].dateDiff, &endDate);
// // Assert for the result // // Assert for the result
// VERIFY_IS_TRUE(isValid); // VERIFY_IS_TRUE(isValid);
@ -390,8 +243,7 @@ TEST_METHOD(TestSubtraction)
// DateTime endDate; // DateTime endDate;
// // Subtract Duration // // Subtract Duration
// bool isValid = m_DateCalcEngine.SubtractDuration(DateUtils::SystemTimeToDateTime(datetimeSubtractCase[testIndex].startDate), // bool isValid = m_DateCalcEngine.SubtractDuration(DateUtils::SystemTimeToDateTime(datetimeSubtractCase[testIndex].startDate), datetimeSubtractCase[testIndex].dateDiff, &endDate);
// datetimeSubtractCase[testIndex].dateDiff, &endDate);
// // assert for the result // // assert for the result
// VERIFY_IS_TRUE(isValid); // VERIFY_IS_TRUE(isValid);
@ -410,226 +262,81 @@ TEST_METHOD(TestSubtraction)
} }
private: private:
}
;
TEST_CLASS(DateCalculatorViewModelTests){ public: TEST_CLASS_INITIALIZE(TestClassSetup){ /* Test Case Data */ };
TEST_CLASS(DateCalculatorViewModelTests)
{
public:
TEST_CLASS_INITIALIZE(TestClassSetup)
{
/* Test Case Data */
// Dates - DD.MM.YYYY // Dates - DD.MM.YYYY
/*31.12.9999*/ date[0].wYear = 9999; /*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;
date[0].wMonth = 12; /*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;
date[0].wDayOfWeek = 5; /*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;
date[0].wDay = 31; /*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;
date[0].wHour = 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;
date[0].wMinute = 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;
date[0].wSecond = 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;
date[0].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;
/*30.12.9999*/ date[1].wYear = 9999; /*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;
date[1].wMonth = 12; /*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;
date[1].wDayOfWeek = 4; /*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;
date[1].wDay = 30; /*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;
date[1].wHour = 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;
date[1].wMinute = 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;
date[1].wSecond = 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[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 // Date Differences
dateDifference[0].year = 1; dateDifference[0].year = 1; dateDifference[0].month = 1;
dateDifference[0].month = 1; dateDifference[1].month = 1; dateDifference[1].day = 10;
dateDifference[1].month = 1;
dateDifference[1].day = 10;
dateDifference[2].day = 2; dateDifference[2].day = 2;
/*date[2]-[0]*/ dateDifference[3].week = 52; /*date[2]-[0]*/ dateDifference[3].week = 52; dateDifference[3].day = 1;
dateDifference[3].day = 1;
/*date[2]-[0]*/ dateDifference[4].year = 1; /*date[2]-[0]*/ dateDifference[4].year = 1;
dateDifference[5].day = 365; dateDifference[5].day = 365;
dateDifference[6].month = 1; dateDifference[6].month = 1;
dateDifference[7].month = 1; dateDifference[7].month = 1; dateDifference[7].day = 2;
dateDifference[7].day = 2;
dateDifference[8].day = 31; dateDifference[8].day = 31;
dateDifference[9].month = 11; dateDifference[9].month = 11; dateDifference[9].day = 1;
dateDifference[9].day = 1; dateDifference[10].year = 8398; dateDifference[10].month = 11; dateDifference[10].day = 30;
dateDifference[10].year = 8398;
dateDifference[10].month = 11;
dateDifference[10].day = 30;
dateDifference[11].year = 2008; dateDifference[11].year = 2008;
dateDifference[12].year = 7991; dateDifference[12].year = 7991; dateDifference[12].month = 11;
dateDifference[12].month = 11; dateDifference[13].week = 416998; dateDifference[13].day = 1;
dateDifference[13].week = 416998;
dateDifference[13].day = 1;
/* Test Cases */ /* Test Cases */
// Date Difference test cases // Date Difference test cases
datetimeDifftest[0].startDate = date[0]; datetimeDifftest[0].startDate = date[0]; datetimeDifftest[0].endDate = date[3]; datetimeDifftest[0].dateDiff = dateDifference[10];
datetimeDifftest[0].endDate = date[3]; datetimeDifftest[1].startDate = date[0]; datetimeDifftest[1].endDate = date[2]; datetimeDifftest[1].dateDiff = dateDifference[5];
datetimeDifftest[0].dateDiff = dateDifference[10]; datetimeDifftest[2].startDate = date[0]; datetimeDifftest[2].endDate = date[2]; datetimeDifftest[2].dateDiff = dateDifference[4];
datetimeDifftest[1].startDate = date[0]; datetimeDifftest[3].startDate = date[0]; datetimeDifftest[3].endDate = date[2]; datetimeDifftest[3].dateDiff = dateDifference[3];
datetimeDifftest[1].endDate = date[2]; datetimeDifftest[4].startDate = date[14]; datetimeDifftest[4].endDate = date[7]; datetimeDifftest[4].dateDiff = dateDifference[7];
datetimeDifftest[1].dateDiff = dateDifference[5]; datetimeDifftest[5].startDate = date[14]; datetimeDifftest[5].endDate = date[7]; datetimeDifftest[5].dateDiff = dateDifference[8];
datetimeDifftest[2].startDate = date[0]; datetimeDifftest[6].startDate = date[11]; datetimeDifftest[6].endDate = date[8]; datetimeDifftest[6].dateDiff = dateDifference[9];
datetimeDifftest[2].endDate = date[2]; datetimeDifftest[7].startDate = date[13]; datetimeDifftest[7].endDate = date[0]; datetimeDifftest[7].dateDiff = dateDifference[12];
datetimeDifftest[2].dateDiff = dateDifference[4]; datetimeDifftest[8].startDate = date[13]; datetimeDifftest[8].endDate = date[0]; datetimeDifftest[8].dateDiff = dateDifference[13];
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) // Date Add Out of Bound test cases (Negative tests)
/*OutofBound*/ datetimeBoundAdd[0].startDate = date[1]; /*OutofBound*/ datetimeBoundAdd[0].startDate = date[1]; datetimeBoundAdd[0].endDate = date[0]; datetimeBoundAdd[0].dateDiff = dateDifference[2]; // on Add date[0] not used
datetimeBoundAdd[0].endDate = date[0]; /*OutofBound*/ datetimeBoundAdd[1].startDate = date[2]; datetimeBoundAdd[1].endDate = date[0]; datetimeBoundAdd[1].dateDiff = dateDifference[11]; // on Add date[0] not used
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) // Date Subtract Out of Bound test cases (Negative tests)
/*OutofBound*/ datetimeBoundSubtract[0].startDate = date[3]; /*OutofBound*/ datetimeBoundSubtract[0].startDate = date[3]; datetimeBoundSubtract[0].endDate = date[0]; datetimeBoundSubtract[0].dateDiff = dateDifference[2]; // on subtract date[0] not used
datetimeBoundSubtract[0].endDate = date[0]; /*OutofBound*/ datetimeBoundSubtract[1].startDate = date[14]; datetimeBoundSubtract[1].endDate = date[0]; datetimeBoundSubtract[1].dateDiff = dateDifference[11]; // on subtract date[0] not used
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) // Date Add test cases (Positive tests)
datetimeAddCase[0].startDate = date[13]; datetimeAddCase[0].startDate = date[13]; datetimeAddCase[0].endDate = date[7]; datetimeAddCase[0].dateDiff = dateDifference[6];// add
datetimeAddCase[0].endDate = date[7]; datetimeAddCase[1].startDate = date[14]; datetimeAddCase[1].endDate = date[5]; datetimeAddCase[1].dateDiff = dateDifference[1];// add
datetimeAddCase[0].dateDiff = dateDifference[6]; // add datetimeAddCase[2].startDate = date[13]; datetimeAddCase[2].endDate = date[6]; datetimeAddCase[2].dateDiff = dateDifference[1];// 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) // Date Subtract test cases (Positive tests)
datetimeSubtractCase[0].startDate = date[14]; datetimeSubtractCase[0].startDate = date[14]; datetimeSubtractCase[0].endDate = date[7]; datetimeSubtractCase[0].dateDiff = dateDifference[6];// subtract
datetimeSubtractCase[0].endDate = date[7]; datetimeSubtractCase[1].startDate = date[6]; datetimeSubtractCase[1].endDate = date[11]; datetimeSubtractCase[1].dateDiff = dateDifference[1];// subtract
datetimeSubtractCase[0].dateDiff = dateDifference[6]; // subtract datetimeSubtractCase[2].startDate = date[9]; datetimeSubtractCase[2].endDate = date[12]; datetimeSubtractCase[2].dateDiff = dateDifference[1];// 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
} }
TEST_METHOD(DateCalcViewModelInitializationTest) TEST_METHOD(DateCalcViewModelInitializationTest)
@ -942,7 +649,12 @@ TEST_METHOD(DateCalcViewModelAddSubtractResultAutomationNameTest)
wstring actualValue = viewModel->StrDateResultAutomationName->Data(); wstring actualValue = viewModel->StrDateResultAutomationName->Data();
// Verify each component is present in the result // Verify each component is present in the result
wstring components[] = { L"dayofweek.full", L"month.full", L"year.full", L"day" }; wstring components[] = {
L"dayofweek.full",
L"month.full",
L"year.full",
L"day"
};
for (const wstring &component : components) for (const wstring &component : components)
{ {
@ -952,6 +664,57 @@ TEST_METHOD(DateCalcViewModelAddSubtractResultAutomationNameTest)
VERIFY_IS_TRUE(actualValue.find(expectedValue) != wstring::npos, message.c_str()); VERIFY_IS_TRUE(actualValue.find(expectedValue) != wstring::npos, message.c_str());
} }
} }
TEST_METHOD(JaEraTransitionAddition)
{
auto viewModel = make_unique<DateCalculationEngine>(CalendarIdentifiers::Japanese);
auto cal = ref new Calendar();
// Showa period ended in Jan 1989.
cal->Year = 1989;
cal->Month = 1;
cal->Day = 1;
auto startTime = cal->GetDateTime();
cal->Year = 1990;
cal->Month = 1;
cal->Day = 1;
// Expect that adding a year across boundaries adds the equivalent in the Gregorian calendar.
auto expectedResult = cal->GetDateTime();
DateDifference duration;
duration.year = 1;
DateTime actualResult;
viewModel->AddDuration(startTime, duration, &actualResult);
VERIFY_ARE_EQUAL(expectedResult.UniversalTime, actualResult.UniversalTime);
} }
;
TEST_METHOD(JaEraTransitionSubtraction)
{
auto viewModel = make_unique<DateCalculationEngine>(CalendarIdentifiers::Japanese);
auto cal = ref new Calendar();
// Showa period ended in Jan 1989.
cal->Year = 1990;
cal->Month = 1;
cal->Day = 1;
auto startTime = cal->GetDateTime();
cal->Year = 1989;
cal->Month = 1;
cal->Day = 1;
// Expect that adding a year across boundaries adds the equivalent in the Gregorian calendar.
auto expectedResult = cal->GetDateTime();
DateDifference duration;
duration.year = 1;
DateTime actualResult;
viewModel->SubtractDuration(startTime, duration, &actualResult);
VERIFY_ARE_EQUAL(expectedResult.UniversalTime, actualResult.UniversalTime);
}
};
} }