-
Notifications
You must be signed in to change notification settings - Fork 197
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add HashVerify and HashProp unit tests + Appveyor
- Loading branch information
Showing
16 changed files
with
743 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,15 @@ | ||
/HashCheck.sdf | ||
/HashCheck.opensdf | ||
*.vcxproj.user | ||
*.csproj.user | ||
*.suo | ||
/Bin | ||
/Obj | ||
/installer/*.exe | ||
/installer/*.exe.sha* | ||
/*.VC.db | ||
/*.VC.VC.opendb | ||
/packages | ||
/UnitTests/bin | ||
/UnitTests/obj | ||
/UnitTests/vectors |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
/** | ||
* HashProp unit tests | ||
* Copyright (C) 2016 Christopher Gurnee. All rights reserved. | ||
* | ||
* Please refer to readme.md for information about this source code. | ||
* Please refer to license.txt for details about distribution and modification. | ||
**/ | ||
|
||
using Xunit; | ||
using TestStack.White; | ||
using TestStack.White.UIItems; | ||
using TestStack.White.UIItems.WindowItems; | ||
using TestStack.White.UIItems.Finders; | ||
using System; | ||
using System.IO; | ||
using System.Diagnostics; | ||
using System.Windows.Automation; | ||
using Microsoft.Win32; | ||
using static UnitTests.ShellExecuteEx; | ||
|
||
namespace UnitTests | ||
{ | ||
public class HashProp | ||
{ | ||
// from HashCheckResources.h | ||
const string IDC_RESULTS = "301"; | ||
const string IDC_STATUSBOX = "302"; | ||
|
||
// Relative path from the class .dll to the test vectors | ||
const string RELATIVE_PATH_PREFIX = @"..\..\vectors\"; | ||
|
||
|
||
static string PATH_PREFIX; | ||
static bool is_com_surrogate; | ||
// | ||
Window OpenHashPropWindow(string filename) | ||
{ | ||
// Combine the path to the class .dll with the relative path to the test vectors | ||
if (PATH_PREFIX == null) | ||
PATH_PREFIX = Path.Combine( | ||
Path.GetDirectoryName( | ||
Uri.UnescapeDataString( | ||
new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).AbsolutePath | ||
) | ||
), | ||
RELATIVE_PATH_PREFIX | ||
); | ||
|
||
// Open the Checksums tab in the shell file properties sheet | ||
SHELLEXECUTEINFO sei = new SHELLEXECUTEINFO(); | ||
sei.cbSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(sei); | ||
sei.fMask = 0x0000010C; // SEE_MASK_INVOKEIDLIST | SEE_MASK_NOASYNC | ||
sei.lpVerb = "Properties"; | ||
sei.lpFile = Path.Combine(PATH_PREFIX, filename); | ||
sei.lpParameters = "Checksums"; | ||
sei.nShow = 1; // SW_SHOWNORMAL | ||
ShellExecuteExW(ref sei); | ||
|
||
TestStack.White.Configuration.CoreAppXmlConfiguration.Instance.FindWindowTimeout = 1500; // 1.5 sec. | ||
|
||
// Find the file properties sheet window | ||
Window prop_window = null; | ||
|
||
// Prior to Windows 10, the file properties sheet opens in the curent process | ||
if (! is_com_surrogate) | ||
{ | ||
Application app = Application.Attach(Process.GetCurrentProcess()); | ||
try | ||
{ | ||
prop_window = app.GetWindow(filename + " Properties"); | ||
is_com_surrogate = false; | ||
} | ||
catch (AutomationException) { } | ||
} | ||
|
||
// Starting with Windows 10, the file properties sheet is hosted in a dllhost COM surrogate | ||
if (prop_window == null) | ||
{ | ||
foreach (Process proc in Process.GetProcessesByName("dllhost")) | ||
{ | ||
Application app = Application.Attach(proc); | ||
try | ||
{ | ||
prop_window = app.GetWindow(filename + " Properties"); | ||
break; | ||
} | ||
catch (AutomationException) { } | ||
} | ||
Assert.NotNull(prop_window); | ||
is_com_surrogate = true; | ||
} | ||
|
||
return prop_window; | ||
} | ||
|
||
|
||
void VerifyResults(Window prop_window, string expected_results) | ||
{ | ||
// Wait for hashing to complete (status contains a summary instead of "Progress") | ||
GroupBox status = prop_window.Get<GroupBox>(SearchCriteria.ByNativeProperty( | ||
AutomationElement.AutomationIdProperty, IDC_STATUSBOX)); | ||
while (status.Name == "Progress") | ||
System.Threading.Thread.Sleep(100); | ||
|
||
// Verify the results | ||
TextBox results = prop_window.Get<TextBox>(SearchCriteria.ByNativeProperty( | ||
AutomationElement.AutomationIdProperty, IDC_RESULTS)); | ||
Assert.Equal(expected_results, results.BulkText, true, true, true); // ignores case, line endings and whitespace changes | ||
} | ||
|
||
|
||
[Theory] | ||
[InlineData( | ||
"SHA256LongMsg.rsp-0000.dat", false, | ||
@" File: SHA256LongMsg.rsp-0000.dat | ||
CRC-32: 29154b1f | ||
SHA-1: a0f8b5c82a0ee5a9119251cd75c55c0ae350923d | ||
SHA-256: 3c593aa539fdcdae516cdf2f15000f6634185c88f505b39775fb9ab137a10aa2 | ||
SHA-512: ae4b5efe9d7e301699dc03ec1bc1f60f83565be9a40d8e38c660a7f9463b22b1ed907f9f4024c9d0ba30c9c38ac12d8cc354d8c4539e63dd6f26a0ce9ce7b71a | ||
" + "\n", | ||
@" File: SHA256LongMsg.rsp-0000.dat | ||
CRC-32: 29154b1f | ||
MD5: 632250fa8b3f9d248e0d37044460a4b7 | ||
SHA-1: a0f8b5c82a0ee5a9119251cd75c55c0ae350923d | ||
SHA-256: 3c593aa539fdcdae516cdf2f15000f6634185c88f505b39775fb9ab137a10aa2 | ||
SHA-512: ae4b5efe9d7e301699dc03ec1bc1f60f83565be9a40d8e38c660a7f9463b22b1ed907f9f4024c9d0ba30c9c38ac12d8cc354d8c4539e63dd6f26a0ce9ce7b71a | ||
SHA3-256: aae3e14fd718aed758574f170c23a2f172a3690587340aa3c5c8d538ebd66bd4 | ||
SHA3-512: 2620b58e343e8a80e091405b65ced686c58c3996854e092d01202dc91598d596aea148131c77513a4ae7f509800abcdb363c45864ef2e291206cd56775ff3e46 | ||
" + "\n")] | ||
[InlineData( | ||
"SHA3_VeryLongMsg.dat", true, | ||
@" File: SHA3_VeryLongMsg.dat | ||
CRC-32: 4ed80f64 | ||
SHA-1: 6ca7cca8ac206ec5a82a612ee5d4ba6ac766d239 | ||
SHA-256: 8716fbf9a5f8c4562b48528e2d3085b64c56b5d1169ccf3295ad03e805580676 | ||
SHA-512: 421b072b4fda96eb569ae55b8a9a5b4b5073a623649bd409dbb999e527372994b3a1a91f53c719837868c7fe11bba67640143255a3fbc5c895d2119274b0caff | ||
" + "\n", | ||
@" File: SHA3_VeryLongMsg.dat | ||
CRC-32: 4ed80f64 | ||
MD5: 1553faf40e3618f9b902c1e559552828 | ||
SHA-1: 6ca7cca8ac206ec5a82a612ee5d4ba6ac766d239 | ||
SHA-256: 8716fbf9a5f8c4562b48528e2d3085b64c56b5d1169ccf3295ad03e805580676 | ||
SHA-512: 421b072b4fda96eb569ae55b8a9a5b4b5073a623649bd409dbb999e527372994b3a1a91f53c719837868c7fe11bba67640143255a3fbc5c895d2119274b0caff | ||
SHA3-256: 6a934f386ff779e33a1068c5f3e4c5c0a117968be4264b8f80ec511a1c0b6eed | ||
SHA3-512: d11fbca35e2383481bd99253a289c035e7a98a36507e4feabf8151fc51e6d77c2f737c4bd747362896ab61df2c066e6a27e7fa2f5bf645b54d98e07e135c4870 | ||
" + "\n")] | ||
// BUG: only works for the English translation | ||
public void HashesTest(string name, bool interrupt, string def_expected_results, string full_expected_results) | ||
{ | ||
// Reset the selected checksums back to the default | ||
RegistryKey reg_key = Registry.CurrentUser.OpenSubKey("SOFTWARE"); | ||
reg_key = reg_key.OpenSubKey("HashCheck", true); // (true == with-write-access) | ||
if (reg_key != null) | ||
reg_key.DeleteValue("Checksums", false); // (false == no-exceptions-if-not-found) | ||
|
||
Window prop_window = OpenHashPropWindow(name); | ||
try | ||
{ | ||
VerifyResults(prop_window, def_expected_results); | ||
|
||
// If we should try to interrupt hash calculation in-progress, restart it | ||
// (VerifyResults() above waits for completion, the following does not) | ||
if (interrupt) | ||
{ | ||
prop_window.Close(); | ||
prop_window = null; | ||
prop_window = OpenHashPropWindow(name); | ||
} | ||
|
||
// Open the options dialog | ||
prop_window.Get<Button>("Options").Click(); | ||
Window options_window = null; | ||
while (true) | ||
{ | ||
foreach (Window mw in prop_window.ModalWindows()) | ||
{ | ||
if (mw.Name.StartsWith("HashCheck Options")) | ||
{ | ||
options_window = mw; | ||
goto options_window_found; | ||
} | ||
} | ||
System.Threading.Thread.Sleep(0); | ||
} | ||
options_window_found: | ||
|
||
// Enable all the hash option checkboxes and click OK | ||
foreach (CheckBox cb in options_window.GetMultiple(SearchCriteria.ByControlType(ControlType.CheckBox))) | ||
cb.State = ToggleState.On; | ||
options_window.Get<Button>("OK").Click(); | ||
|
||
VerifyResults(prop_window, full_expected_results); | ||
} | ||
finally | ||
{ | ||
if (prop_window != null) | ||
prop_window.Close(); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/** | ||
* HashVerify unit tests | ||
* Copyright (C) 2016 Christopher Gurnee. All rights reserved. | ||
* | ||
* Please refer to readme.md for information about this source code. | ||
* Please refer to license.txt for details about distribution and modification. | ||
**/ | ||
|
||
using Xunit; | ||
using TestStack.White; | ||
using TestStack.White.UIItems; | ||
using TestStack.White.UIItems.Finders; | ||
using System; | ||
using System.IO; | ||
using System.Diagnostics; | ||
using System.Windows.Automation; | ||
|
||
namespace UnitTests | ||
{ | ||
public class HashVerifySetup | ||
{ | ||
// Relative path from the class .dll to the test vectors | ||
const string RELATIVE_PATH_PREFIX = @"..\..\vectors\"; | ||
internal string PATH_PREFIX; | ||
|
||
internal Application app; | ||
|
||
public HashVerifySetup() | ||
{ | ||
// Combine the path to the class .dll with the relative path to the test vectors | ||
PATH_PREFIX = Path.Combine( | ||
Path.GetDirectoryName( | ||
Uri.UnescapeDataString( | ||
new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).AbsolutePath | ||
) | ||
), | ||
RELATIVE_PATH_PREFIX | ||
); | ||
|
||
Process proc = Process.GetCurrentProcess(); | ||
app = Application.Attach(proc); | ||
|
||
// Workaround required when debugging unit tests in the VS GUI - | ||
// for some reason the first time this is called the DLL loads but HashVerify doesn't start | ||
if (Debugger.IsAttached && proc.MainModule.ModuleName.StartsWith("vstest.executionengine.")) | ||
Process.Start(Path.Combine(PATH_PREFIX, "SHA3_256ShortMsg.rsp.sha3-256")); | ||
} | ||
} | ||
|
||
public class HashVerify : IClassFixture<HashVerifySetup> | ||
{ | ||
// from HashCheckResources.h | ||
const string IDC_MATCH_RESULTS = "404"; | ||
const string IDC_PENDING_RESULTS = "410"; | ||
|
||
HashVerifySetup common; | ||
|
||
public HashVerify(HashVerifySetup c) | ||
{ | ||
common = c; | ||
} | ||
|
||
[Theory] | ||
[InlineData("SHA1ShortMsg.rsp.sha1")] | ||
[InlineData("SHA1LongMsg.rsp.sha1")] | ||
[InlineData("SHA256ShortMsg.rsp.sha256")] | ||
[InlineData("SHA256LongMsg.rsp.sha256")] | ||
[InlineData("SHA512ShortMsg.rsp.sha512")] | ||
[InlineData("SHA512LongMsg.rsp.sha512")] | ||
[InlineData("SHA3_256ShortMsg.rsp.sha3-256")] | ||
[InlineData("SHA3_256LongMsg.rsp.sha3-256")] | ||
[InlineData("SHA3_512ShortMsg.rsp.sha3-512")] | ||
[InlineData("SHA3_512LongMsg.rsp.sha3-512")] | ||
[InlineData("hashcheck.md5")] | ||
[InlineData("hashcheck.sha1")] | ||
public void NistTest(string name) | ||
{ | ||
// This opens a HashCheck Verify window in the current process | ||
Process.Start(Path.Combine(common.PATH_PREFIX, name)); | ||
|
||
var verify_window = common.app.GetWindow(name); | ||
try | ||
{ | ||
// Wait for hashing to complete (there are 0 pending results) | ||
var re0 = new System.Text.RegularExpressions.Regex(@"\b0\b"); | ||
Label pending_results = verify_window.Get<Label>(SearchCriteria.ByNativeProperty( | ||
AutomationElement.AutomationIdProperty, IDC_PENDING_RESULTS)); | ||
while (! re0.IsMatch(pending_results.Text)) | ||
System.Threading.Thread.Sleep(0); | ||
|
||
// On success, the hash matches should be "# of #" where the #'s are the same | ||
Label match_results = verify_window.Get<Label>(SearchCriteria.ByNativeProperty( | ||
AutomationElement.AutomationIdProperty, IDC_MATCH_RESULTS)); | ||
Assert.Matches(@"\b(\d{2,3})\b.*\b\1\b", match_results.Text); | ||
} | ||
finally | ||
{ | ||
verify_window.Close(); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.