diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-hex/Format-Hex.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-hex/Format-Hex.cs
index 6bb1f37a9c..810534a9ff 100644
--- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-hex/Format-Hex.cs
+++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-hex/Format-Hex.cs
@@ -17,12 +17,30 @@ namespace Microsoft.PowerShell.Commands
/// Displays the hexadecimal equivalent of the input data.
///
[Cmdlet(VerbsCommon.Format, "Hex", HelpUri = "https://go.microsoft.com/fwlink/?LinkId=526919")]
- [OutputType(typeof(Microsoft.PowerShell.Commands.ByteCollection))]
+ [OutputType(typeof(ByteCollection))]
[Alias("fhx")]
public sealed class FormatHex : PSCmdlet
{
private const int BUFFERSIZE = 16;
+ ///
+ /// For cases where a homogenous collection of bytes or other items are directly piped in, we collect all the
+ /// bytes in a List<byte> and then output the formatted result all at once in EndProcessing().
+ ///
+ private readonly List _inputBuffer = new List();
+
+ ///
+ /// Expect to group s by default. When receiving input that should not be grouped,
+ /// e.g., arrays, strings, FileInfo objects, this flag will be disabled until the next groupable
+ /// is received over the pipeline.
+ ///
+ private bool _groupInput = true;
+
+ ///
+ /// Keep track of prior input types to determine if we're given a heterogenous collection.
+ ///
+ private Type _lastInputType;
+
#region Parameters
///
@@ -85,19 +103,28 @@ namespace Microsoft.PowerShell.Commands
///
protected override void ProcessRecord()
{
- if (string.Equals(this.ParameterSetName, "ByInputObject", StringComparison.OrdinalIgnoreCase))
+ if (string.Equals(ParameterSetName, "ByInputObject", StringComparison.OrdinalIgnoreCase))
{
- ProcessObjectContent(InputObject);
+ ProcessInputObjects(InputObject);
}
else
{
- List pathsToProcess = string.Equals(this.ParameterSetName, "LiteralPath", StringComparison.OrdinalIgnoreCase) ?
- ResolvePaths(LiteralPath, true) : ResolvePaths(Path, false);
+ List pathsToProcess = string.Equals(ParameterSetName, "LiteralPath", StringComparison.OrdinalIgnoreCase)
+ ? ResolvePaths(LiteralPath, true)
+ : ResolvePaths(Path, false);
ProcessPath(pathsToProcess);
}
}
+ ///
+ /// Implements the EndProcessing method for the FormatHex command.
+ ///
+ protected override void EndProcessing()
+ {
+ FlushInputBuffer();
+ }
+
#endregion
#region Paths
@@ -114,7 +141,6 @@ namespace Microsoft.PowerShell.Commands
{
List pathsToProcess = new List();
ProviderInfo provider = null;
- PSDriveInfo drive = null;
foreach (string currentPath in path)
{
@@ -122,7 +148,7 @@ namespace Microsoft.PowerShell.Commands
if (literalPath)
{
- newPaths.Add(Context.SessionState.Path.GetUnresolvedProviderPathFromPSPath(currentPath, out provider, out drive));
+ newPaths.Add(Context.SessionState.Path.GetUnresolvedProviderPathFromPSPath(currentPath, out provider, out _));
}
else
{
@@ -183,34 +209,32 @@ namespace Microsoft.PowerShell.Commands
try
{
- using (BinaryReader reader = new BinaryReader(File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read)))
+ using var reader = new BinaryReader(File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read));
+ long offset = Offset;
+ int bytesRead = 0;
+ long count = 0;
+
+ reader.BaseStream.Position = Offset;
+
+ while ((bytesRead = reader.Read(buffer)) > 0)
{
- long offset = Offset;
- int bytesRead = 0;
- long count = 0;
-
- reader.BaseStream.Position = Offset;
-
- while ((bytesRead = reader.Read(buffer)) > 0)
+ count += bytesRead;
+ if (count > Count)
{
- count += bytesRead;
- if (count > Count)
- {
- bytesRead -= (int)(count - Count);
- WriteHexadecimal(buffer.Slice(0, bytesRead), path, offset);
- break;
- }
-
+ bytesRead -= (int)(count - Count);
WriteHexadecimal(buffer.Slice(0, bytesRead), path, offset);
-
- offset += bytesRead;
+ break;
}
+
+ WriteHexadecimal(buffer.Slice(0, bytesRead), path, offset);
+
+ offset += bytesRead;
}
}
- catch (IOException ioException)
+ catch (IOException fileException)
{
// IOException takes care of FileNotFoundException, DirectoryNotFoundException, and PathTooLongException
- WriteError(new ErrorRecord(ioException, "FormatHexIOError", ErrorCategory.WriteError, path));
+ WriteError(new ErrorRecord(fileException, "FormatHexIOError", ErrorCategory.WriteError, path));
}
catch (ArgumentException argException)
{
@@ -218,11 +242,19 @@ namespace Microsoft.PowerShell.Commands
}
catch (NotSupportedException notSupportedException)
{
- WriteError(new ErrorRecord(notSupportedException, "FormatHexPathRefersToANonFileDevice", ErrorCategory.InvalidArgument, path));
+ WriteError(new ErrorRecord(
+ notSupportedException,
+ "FormatHexPathRefersToANonFileDevice",
+ ErrorCategory.InvalidArgument,
+ path));
}
catch (SecurityException securityException)
{
- WriteError(new ErrorRecord(securityException, "FormatHexUnauthorizedAccessError", ErrorCategory.PermissionDenied, path));
+ WriteError(new ErrorRecord(
+ securityException,
+ "FormatHexUnauthorizedAccessError",
+ ErrorCategory.PermissionDenied,
+ path));
}
}
@@ -230,37 +262,95 @@ namespace Microsoft.PowerShell.Commands
#region InputObjects
+ private void ProcessString(string originalString)
+ {
+ Span bytes = Encoding.GetBytes(originalString);
+
+ int offset = Math.Min(bytes.Length, Offset < int.MaxValue ? (int)Offset : int.MaxValue);
+ int count = Math.Min(bytes.Length - offset, Count < int.MaxValue ? (int)Count : int.MaxValue);
+
+ if (offset != 0 || count != bytes.Length)
+ {
+ WriteHexadecimal(bytes.Slice(offset, count), offset: 0, label: GetGroupLabel(typeof(string)));
+ }
+ else
+ {
+ WriteHexadecimal(bytes, offset: 0, label: GetGroupLabel(typeof(string)));
+ }
+ }
+
+ private static readonly Random _idGenerator = new Random();
+ private static string GetGroupLabel(Type inputType)
+ => string.Format("{0} ({1}) <{2:X8}>", inputType.Name, inputType.FullName, _idGenerator.Next());
+
+ private void FlushInputBuffer()
+ {
+ if (_inputBuffer.Count == 0)
+ {
+ return;
+ }
+
+ int offset = Math.Min(_inputBuffer.Count, Offset < int.MaxValue ? (int)Offset : int.MaxValue);
+ int count = Math.Min(_inputBuffer.Count - offset, Count < int.MaxValue ? (int)Count : int.MaxValue);
+
+ if (offset != 0 || count != _inputBuffer.Count)
+ {
+ WriteHexadecimal(
+ _inputBuffer.GetRange(offset, count).ToArray(),
+ offset: 0,
+ label: GetGroupLabel(_lastInputType));
+ }
+ else
+ {
+ WriteHexadecimal(
+ _inputBuffer.ToArray(),
+ offset: 0,
+ label: GetGroupLabel(_lastInputType));
+ }
+
+ // Reset flags so we can go back to filling up the buffer when needed.
+ _lastInputType = null;
+ _groupInput = true;
+ _inputBuffer.Clear();
+ }
+
///
/// Creates a byte array from the object passed to the cmdlet (based on type) and passes
/// that array on to the WriteHexadecimal method to output.
///
/// The pipeline input object being processed.
- private void ProcessObjectContent(PSObject inputObject)
+ private void ProcessInputObjects(PSObject inputObject)
{
object obj = inputObject.BaseObject;
- if (obj is System.IO.FileSystemInfo fsi)
+ if (obj is FileSystemInfo fsi)
{
+ // Output already processed objects first, then process the file input.
+ FlushInputBuffer();
string[] path = { fsi.FullName };
List pathsToProcess = ResolvePaths(path, true);
ProcessPath(pathsToProcess);
return;
}
- byte[] inputBytes = ConvertToByteArray(obj);
+ if (obj is string str)
+ {
+ // Output already processed objects first, then process the string input.
+ FlushInputBuffer();
+ ProcessString(str);
+ return;
+ }
+
+ byte[] inputBytes = ConvertToBytes(obj);
+
+ if (!_groupInput)
+ {
+ FlushInputBuffer();
+ }
if (inputBytes != null)
{
- int offset = Math.Min(inputBytes.Length, Offset < (long)int.MaxValue ? (int)Offset : int.MaxValue);
- int count = Math.Min(inputBytes.Length - offset, Count < (long)int.MaxValue ? (int)Count : int.MaxValue);
- if (offset != 0 || count != inputBytes.Length)
- {
- WriteHexadecimal(inputBytes.AsSpan().Slice(offset, count), null, 0);
- }
- else
- {
- WriteHexadecimal(inputBytes, null, 0);
- }
+ _inputBuffer.AddRange(inputBytes);
}
else
{
@@ -280,14 +370,9 @@ namespace Microsoft.PowerShell.Commands
///
/// The object to convert.
/// Returns a byte array of the input values, or null if there is no available conversion path.
- private byte[] ConvertToByteArray(object inputObject)
+ private byte[] ConvertToBytes(object inputObject)
{
- if (inputObject is string str)
- {
- return Encoding.GetBytes(str);
- }
-
- var baseType = inputObject.GetType();
+ Type baseType = inputObject.GetType();
byte[] result = null;
int elements = 1;
bool isArray = false;
@@ -295,6 +380,10 @@ namespace Microsoft.PowerShell.Commands
bool isEnum = false;
if (baseType.IsArray)
{
+ FlushInputBuffer();
+ _lastInputType = baseType;
+ _groupInput = false;
+
baseType = baseType.GetElementType();
dynamic dynamicObject = inputObject;
elements = (int)dynamicObject.Length;
@@ -309,6 +398,16 @@ namespace Microsoft.PowerShell.Commands
if (baseType.IsPrimitive && elements > 0)
{
+ if (_groupInput)
+ {
+ if (_lastInputType != null && baseType != _lastInputType)
+ {
+ _groupInput = false;
+ }
+
+ _lastInputType = baseType;
+ }
+
if (baseType == typeof(bool))
{
isBool = true;
@@ -364,21 +463,44 @@ namespace Microsoft.PowerShell.Commands
#region Output
///
- /// Outputs the hexadecimial representation of the input data.
+ /// Outputs the hexadecimal representation of the input data.
///
- /// Bytes for the hexadecimial representation.
+ /// Bytes for the hexadecimal representation.
/// File path.
/// Offset in the file.
private void WriteHexadecimal(Span inputBytes, string path, long offset)
{
- ByteCollection byteCollectionObject = new ByteCollection((ulong)offset, inputBytes.ToArray(), path);
- WriteObject(byteCollectionObject);
+ var bytesPerObject = 16;
+ for (int index = 0; index < inputBytes.Length; index += bytesPerObject)
+ {
+ var count = inputBytes.Length - index < bytesPerObject
+ ? inputBytes.Length - index
+ : bytesPerObject;
+ var bytes = inputBytes.Slice(index, count);
+ WriteObject(new ByteCollection((ulong)index + (ulong)offset, bytes.ToArray(), path));
+ }
}
- private void WriteHexadecimal(byte[] inputBytes, string path, long offset)
+ ///
+ /// Outputs the hexadecimal representation of the input data.
+ ///
+ /// Bytes for the hexadecimal representation.
+ /// Offset in the file.
+ ///
+ /// The label for the byte group. This may be a file path, a string value, or a
+ /// formatted identifying string for the group.
+ ///
+ private void WriteHexadecimal(Span inputBytes, long offset, string label)
{
- ByteCollection byteCollectionObject = new ByteCollection((ulong)offset, inputBytes, path);
- WriteObject(byteCollectionObject);
+ var bytesPerObject = 16;
+ for (int index = 0; index < inputBytes.Length; index += bytesPerObject)
+ {
+ var count = inputBytes.Length - index < bytesPerObject
+ ? inputBytes.Length - index
+ : bytesPerObject;
+ var bytes = inputBytes.Slice(index, count);
+ WriteObject(new ByteCollection((ulong)index + (ulong)offset, label, bytes.ToArray()));
+ }
}
#endregion
diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/UtilityCommon.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/UtilityCommon.cs
index 6e167f6182..f3c9d86a8e 100644
--- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/UtilityCommon.cs
+++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/UtilityCommon.cs
@@ -95,26 +95,24 @@ namespace Microsoft.PowerShell.Commands
public class ByteCollection
{
///
- /// ByteCollection constructor.
+ /// Initializes a new instance of the class.
///
/// The Offset address to be used while displaying the bytes in the collection.
/// Underlying bytes stored in the collection.
/// Indicates the path of the file whose contents are wrapped in the ByteCollection.
[Obsolete("The constructor is deprecated.", true)]
- public ByteCollection(UInt32 offset, byte[] value, string path)
+ public ByteCollection(uint offset, byte[] value, string path)
+ : this((ulong)offset, value, path)
{
- Offset64 = offset;
- Bytes = value;
- Path = path;
}
///
- /// Initializes a new instance of ByteCollection.
+ /// Initializes a new instance of the class.
///
/// The Offset address to be used while displaying the bytes in the collection.
/// Underlying bytes stored in the collection.
/// Indicates the path of the file whose contents are wrapped in the ByteCollection.
- public ByteCollection(UInt64 offset, byte[] value, string path)
+ public ByteCollection(ulong offset, byte[] value, string path)
{
if (value == null)
{
@@ -124,31 +122,26 @@ namespace Microsoft.PowerShell.Commands
Offset64 = offset;
Bytes = value;
Path = path;
+ Label = path;
}
///
- /// ByteCollection constructor.
+ /// Initializes a new instance of the class.
///
/// The Offset address to be used while displaying the bytes in the collection.
/// Underlying bytes stored in the collection.
[Obsolete("The constructor is deprecated.", true)]
- public ByteCollection(UInt32 offset, byte[] value)
+ public ByteCollection(uint offset, byte[] value)
+ : this((ulong)offset, value)
{
- if (value == null)
- {
- throw PSTraceSource.NewArgumentNullException("value");
- }
-
- Offset64 = offset;
- Bytes = value;
}
///
- /// ByteCollection constructor.
+ /// Initializes a new instance of the class.
///
/// The Offset address to be used while displaying the bytes in the collection.
/// Underlying bytes stored in the collection.
- public ByteCollection(UInt64 offset, byte[] value)
+ public ByteCollection(ulong offset, byte[] value)
{
if (value == null)
{
@@ -160,7 +153,21 @@ namespace Microsoft.PowerShell.Commands
}
///
- /// ByteCollection constructor.
+ /// Initializes a new instance of the class.
+ ///
+ /// The Offset address to be used while displaying the bytes in the collection.
+ ///
+ /// The label for the byte group. This may be a file path or a formatted identifying string for the group.
+ ///
+ /// Underlying bytes stored in the collection.
+ public ByteCollection(ulong offset, string label, byte[] value)
+ : this(offset, value)
+ {
+ Label = label;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
///
/// Underlying bytes stored in the collection.
public ByteCollection(byte[] value)
@@ -206,6 +213,82 @@ namespace Microsoft.PowerShell.Commands
///
public string Path { get; private set; }
+ ///
+ /// Gets the hexadecimal representation of the value.
+ ///
+ public string HexOffset { get => string.Format(CultureInfo.CurrentCulture, "{0:X16}", Offset64); }
+
+ ///
+ /// Gets the type of the input objects used to create the .
+ ///
+ public string Label { get; private set; }
+
+ private const int BytesPerLine = 16;
+
+ private string _hexBytes = string.Empty;
+
+ ///
+ /// Gets a space-delimited string of the in this
+ /// in hexadecimal format.
+ ///
+ public string HexBytes
+ {
+ get
+ {
+ if (_hexBytes == string.Empty)
+ {
+ StringBuilder line = new StringBuilder(BytesPerLine * 3);
+
+ foreach (var currentByte in Bytes)
+ {
+ line.AppendFormat(CultureInfo.CurrentCulture, "{0:X2} ", currentByte);
+ }
+
+ _hexBytes = line.ToString().Trim();
+ }
+
+ return _hexBytes;
+ }
+ }
+
+ private string _ascii = string.Empty;
+
+ ///
+ /// Gets the ASCII string representation of the in this .
+ ///
+ ///
+ public string Ascii
+ {
+ get
+ {
+ if (_ascii == string.Empty)
+ {
+ StringBuilder ascii = new StringBuilder(BytesPerLine);
+
+ foreach (var currentByte in Bytes)
+ {
+ var currentChar = (char)currentByte;
+ if (currentChar == 0x0)
+ {
+ ascii.Append(' ');
+ }
+ else if (char.IsControl(currentChar))
+ {
+ ascii.Append((char)0xFFFD);
+ }
+ else
+ {
+ ascii.Append(currentChar);
+ }
+ }
+
+ _ascii = ascii.ToString();
+ }
+
+ return _ascii;
+ }
+ }
+
///
/// Displays the hexadecimal format of the bytes stored in the collection.
///
@@ -213,11 +296,11 @@ namespace Microsoft.PowerShell.Commands
public override string ToString()
{
const int BytesPerLine = 16;
- const string LineFormat = "{0:X20} ";
+ const string LineFormat = "{0:X16} ";
- // '20 + 3' comes from format "{0:X20} ".
- // '20' comes from '[Uint64]::MaxValue.ToString().Length'.
- StringBuilder nextLine = new StringBuilder(20 + 3 + (BytesPerLine * 3));
+ // '16 + 3' comes from format "{0:X16} ".
+ // '16' comes from '[Uint64]::MaxValue.ToString("X").Length'.
+ StringBuilder nextLine = new StringBuilder(16 + 3 + (BytesPerLine * 3));
StringBuilder asciiEnd = new StringBuilder(BytesPerLine);
// '+1' comes from 'result.Append(nextLine.ToString() + " " + asciiEnd.ToString());' below.
@@ -225,10 +308,8 @@ namespace Microsoft.PowerShell.Commands
if (Bytes.Length > 0)
{
- Int64 charCounter = 0;
+ long charCounter = 0;
- // ToString() in invoked thrice by the F&O for the same content.
- // Hence making sure that Offset is not getting incremented thrice for the same bytes being displayed.
var currentOffset = Offset64;
nextLine.AppendFormat(CultureInfo.InvariantCulture, LineFormat, currentOffset);
@@ -240,13 +321,18 @@ namespace Microsoft.PowerShell.Commands
// If the character is printable, add its ascii representation to
// the right-hand side. Otherwise, add a dot to the right hand side.
- if ((currentByte >= 0x20) && (currentByte <= 0xFE))
+ var currentChar = (char)currentByte;
+ if (currentChar == 0x0)
{
- asciiEnd.Append((char)currentByte);
+ asciiEnd.Append(' ');
+ }
+ else if (char.IsControl(currentChar))
+ {
+ asciiEnd.Append((char)0xFFFD);
}
else
{
- asciiEnd.Append('.');
+ asciiEnd.Append(currentChar);
}
charCounter++;
@@ -262,7 +348,7 @@ namespace Microsoft.PowerShell.Commands
nextLine.AppendFormat(CultureInfo.InvariantCulture, LineFormat, currentOffset);
// Adding a newline to support long inputs strings flowing through InputObject parameterset.
- if ((charCounter <= Bytes.Length) && string.IsNullOrEmpty(this.Path))
+ if ((charCounter <= Bytes.Length) && string.IsNullOrEmpty(Path))
{
result.AppendLine();
}
diff --git a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs
index 6771c91c22..30118933b9 100644
--- a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs
+++ b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs
@@ -18,22 +18,8 @@ namespace System.Management.Automation.Runspaces
.EndEntry()
.EndControl();
- var ByteCollection_GroupHeader = CustomControl.Create()
- .StartEntry()
- .StartFrame()
- .AddScriptBlockExpressionBinding(@"
- $header = "" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F""
- if($_.Path) { $header = "" "" + [Microsoft.PowerShell.Commands.UtilityResources]::FormatHexPathPrefix + $_.Path + ""`r`n`r`n"" + $header }
-
- $header
- ")
- .EndFrame()
- .EndEntry()
- .EndControl();
-
var sharedControls = new CustomControl[] {
- AvailableModules_GroupingFormat,
- ByteCollection_GroupHeader
+ AvailableModules_GroupingFormat
};
yield return new ExtendedTypeDefinition(
@@ -167,10 +153,6 @@ namespace System.Management.Automation.Runspaces
"System.Management.Automation.InformationRecord",
ViewsOf_System_Management_Automation_InformationRecord());
- yield return new ExtendedTypeDefinition(
- "Microsoft.PowerShell.Commands.ByteCollection",
- ViewsOf_Microsoft_PowerShell_Commands_ByteCollection(sharedControls));
-
yield return new ExtendedTypeDefinition(
"System.Exception",
ViewsOf_System_Exception());
@@ -254,6 +236,10 @@ namespace System.Management.Automation.Runspaces
yield return new ExtendedTypeDefinition(
"Microsoft.PowerShell.MarkdownRender.PSMarkdownOptionInfo",
ViewsOf_Microsoft_PowerShell_MarkdownRender_MarkdownOptionInfo());
+
+ yield return new ExtendedTypeDefinition(
+ "Microsoft.PowerShell.Commands.ByteCollection",
+ ViewsOf_Microsoft_PowerShell_Commands_ByteCollection());
}
private static IEnumerable ViewsOf_System_RuntimeType()
@@ -1077,19 +1063,6 @@ namespace System.Management.Automation.Runspaces
.EndControl());
}
- private static IEnumerable ViewsOf_Microsoft_PowerShell_Commands_ByteCollection(CustomControl[] sharedControls)
- {
- yield return new FormatViewDefinition("ByteCollection",
- CustomControl.Create()
- .GroupByScriptBlock("if($_.Path) { $_.Path } else { $_.GetHashCode() }", customControl: sharedControls[1])
- .StartEntry()
- .StartFrame()
- .AddScriptBlockExpressionBinding(@"$_.ToString()")
- .EndFrame()
- .EndEntry()
- .EndControl());
- }
-
private static IEnumerable ViewsOf_System_Exception()
{
yield return new FormatViewDefinition("Exception",
@@ -1630,5 +1603,22 @@ namespace System.Management.Automation.Runspaces
.EndEntry()
.EndList());
}
+
+ private static IEnumerable ViewsOf_Microsoft_PowerShell_Commands_ByteCollection()
+ {
+ yield return new FormatViewDefinition(
+ "Microsoft.PowerShell.Commands.ByteCollection",
+ TableControl.Create()
+ .AddHeader(Alignment.Right, label: "Offset", width: 16)
+ .AddHeader(Alignment.Left, label: "Bytes\n00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F", width: 47)
+ .AddHeader(Alignment.Left, label: "Ascii", width: 16)
+ .StartRowDefinition()
+ .AddPropertyColumn("HexOffset")
+ .AddPropertyColumn("HexBytes")
+ .AddPropertyColumn("Ascii")
+ .EndRowDefinition()
+ .GroupByProperty("Label")
+ .EndTable());
+ }
}
}
diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Hex.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Hex.Tests.ps1
index baba808a43..875273acac 100644
--- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Hex.Tests.ps1
+++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Hex.Tests.ps1
@@ -6,10 +6,8 @@
<#
Purpose:
Verify Format-Hex displays the Hexadecimal value for the input data.
-
Action:
Run Format-Hex.
-
Expected Result:
Hexadecimal equivalent of the input data is displayed.
#>
@@ -21,21 +19,27 @@ Describe "FormatHex" -tags "CI" {
$newline = [Environment]::Newline
Setup -d FormatHexDataDir
+ $inputFile1 = New-Item -Path "$TestDrive/SourceFile-1.txt"
$inputText1 = 'Hello World'
+ Set-Content -LiteralPath $inputFile1.FullName -Value $inputText1 -NoNewline
+
+ $inputFile2 = New-Item -Path "$TestDrive/SourceFile-2.txt"
$inputText2 = 'More text'
+ Set-Content -LiteralPath $inputFile2.FullName -Value $inputText2 -NoNewline
+
+ $inputFile3 = New-Item -Path "$TestDrive/SourceFile literal [3].txt"
$inputText3 = 'Literal path'
+ Set-Content -LiteralPath $inputFile3.FullName -Value $inputText3 -NoNewline
+
+ $inputFile4 = New-Item -Path "$TestDrive/SourceFile-4.txt"
$inputText4 = 'Now is the winter of our discontent'
- $inputFile1 = setup -f "FormatHexDataDir/SourceFile-1.txt" -content $inputText1 -pass
- $inputFile2 = setup -f "FormatHexDataDir/SourceFile-2.txt" -content $inputText2 -pass
- $inputFile3 = setup -f "FormatHexDataDir/SourceFile literal [3].txt" -content $inputText3 -pass
- $inputFile4 = setup -f "FormatHexDataDir/SourceFile-4.txt" -content $inputText4 -pass
+ Set-Content -LiteralPath $inputFile4.FullName -Value $inputText4 -NoNewline
$certificateProvider = Get-ChildItem Cert:\CurrentUser\My\ -ErrorAction SilentlyContinue
$thumbprint = $null
$certProviderAvailable = $false
- if ($certificateProvider.Count -gt 0)
- {
+ if ($certificateProvider.Count -gt 0) {
$thumbprint = $certificateProvider[0].Thumbprint
$certProviderAvailable = $true
}
@@ -44,100 +48,90 @@ Describe "FormatHex" -tags "CI" {
}
Context "InputObject Paramater" {
+ BeforeAll {
+ enum TestEnum {
+ TestOne = 1; TestTwo = 2; TestThree = 3; TestFour = 4
+ }
+ Add-Type -TypeDefinition @'
+public enum TestSByteEnum : sbyte {
+ One = -1,
+ Two = -2,
+ Three = -3,
+ Four = -4
+}
+'@
+ }
+
$testCases = @(
@{
- Name = "Can process byte type 'fhx -InputObject [byte]5'"
- InputObject = [byte]5
- Count = 1
+ Name = "Can process byte type 'fhx -InputObject [byte]5'"
+ InputObject = [byte]5
+ Count = 1
ExpectedResult = "00000000 05"
}
@{
- Name = "Can process byte[] type 'fhx -InputObject [byte[]](1,2,3,4,5)'"
- InputObject = [byte[]](1,2,3,4,5)
- Count = 1
+ Name = "Can process byte[] type 'fhx -InputObject [byte[]](1,2,3,4,5)'"
+ InputObject = [byte[]](1, 2, 3, 4, 5)
+ Count = 1
ExpectedResult = "00000000 01 02 03 04 05 ....."
}
@{
- Name = "Can process int type 'fhx -InputObject 7'"
- InputObject = 7
- Count = 1
+ Name = "Can process int type 'fhx -InputObject 7'"
+ InputObject = 7
+ Count = 1
ExpectedResult = "00000000 07 00 00 00 ...."
}
@{
- Name = "Can process int[] type 'fhx -InputObject [int[]](5,6,7,8)'"
- InputObject = [int[]](5,6,7,8)
- Count = 1
+ Name = "Can process int[] type 'fhx -InputObject [int[]](5,6,7,8)'"
+ InputObject = [int[]](5, 6, 7, 8)
+ Count = 1
ExpectedResult = "00000000 05 00 00 00 06 00 00 00 07 00 00 00 08 00 00 00 ................"
}
@{
- Name = "Can process int32 type 'fhx -InputObject [int32]2032'"
- InputObject = [int32]2032
- Count = 1
+ Name = "Can process int32 type 'fhx -InputObject [int32]2032'"
+ InputObject = [int32]2032
+ Count = 1
ExpectedResult = "00000000 F0 07 00 00 ð..."
}
@{
- Name = "Can process int32[] type 'fhx -InputObject [int32[]](2032, 2033, 2034)'"
- InputObject = [int32[]](2032, 2033, 2034)
- Count = 1
- ExpectedResult = "00000000000000000000 F0 07 00 00 F1 07 00 00 F2 07 00 00 ð...ñ...ò..."
+ Name = "Can process int32[] type 'fhx -InputObject [int32[]](2032, 2033, 2034)'"
+ InputObject = [int32[]](2032, 2033, 2034)
+ Count = 1
+ ExpectedResult = "0000000000000000 F0 07 00 00 F1 07 00 00 F2 07 00 00 ð...ñ...ò..."
}
@{
- Name = "Can process Int64 type 'fhx -InputObject [Int64]9223372036854775807'"
- InputObject = [Int64]9223372036854775807
- Count = 1
- ExpectedResult = "00000000000000000000 FF FF FF FF FF FF FF 7F ......."
+ Name = "Can process Int64 type 'fhx -InputObject [Int64]9223372036854775807'"
+ InputObject = [Int64]9223372036854775807
+ Count = 1
+ ExpectedResult = "0000000000000000 FF FF FF FF FF FF FF 7F ÿÿÿÿÿÿÿ�"
}
@{
- Name = "Can process Int64[] type 'fhx -InputObject [Int64[]](9223372036852,9223372036853)'"
- InputObject = [Int64[]](9223372036852,9223372036853)
- Count = 1
- ExpectedResult = "00000000000000000000 F4 5A D0 7B 63 08 00 00 F5 5A D0 7B 63 08 00 00 ôZÐ{c...õZÐ{c..."
+ Name = "Can process Int64[] type 'fhx -InputObject [Int64[]](9223372036852,9223372036853)'"
+ InputObject = [Int64[]](9223372036852, 9223372036853)
+ Count = 1
+ ExpectedResult = "0000000000000000 F4 5A D0 7B 63 08 00 00 F5 5A D0 7B 63 08 00 00 ôZÐ{c...õZÐ{c..."
}
@{
- Name = "Can process string type 'fhx -InputObject hello world'"
- InputObject = "hello world"
- Count = 1
- ExpectedResult = "00000000000000000000 68 65 6C 6C 6F 20 77 6F 72 6C 64 hello world"
+ Name = "Can process string type 'fhx -InputObject hello world'"
+ InputObject = "hello world"
+ Count = 1
+ ExpectedResult = "0000000000000000 68 65 6C 6C 6F 20 77 6F 72 6C 64 hello world"
}
@{
- Name = "Can process enum type 'fhx -InputObject ([DisplayHintType]::DateTime)'"
- InputObject = [Microsoft.PowerShell.Commands.DisplayHintType]::DateTime
- Count = 1
- ExpectedResult = "00000000000000000000 02 00 00 00 ...."
+ Name = "Can process PS-native enum array '[TestEnum[]]('TestOne', 'TestTwo', 'TestThree', 'TestFour') | fhx'"
+ InputObject = [TestEnum[]]('TestOne', 'TestTwo', 'TestThree', 'TestFour')
+ Count = 1
+ ExpectedResult = "0000000000000000 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 ................"
}
@{
- Name = "Can process DisplayHintType[] type 'fhx -InputObject ([DisplayHintType[]](DateTime, Time))'"
- InputObject = [Microsoft.PowerShell.Commands.DisplayHintType[]]([Microsoft.PowerShell.Commands.DisplayHintType]::DateTime)
- Count = 1
- ExpectedResult = "00000000000000000000 02 00 00 00 ...."
- }
- @{
- Name = "Can process DisplayHintType[] type 'fhx -InputObject ([DisplayHintType[]](DateTime, Time))'"
- InputObject = [Microsoft.PowerShell.Commands.DisplayHintType[]]([Microsoft.PowerShell.Commands.DisplayHintType]::DateTime, [Microsoft.PowerShell.Commands.DisplayHintType]::Time)
- Count = 1
- ExpectedResult = "00000000000000000000 02 00 00 00 01 00 00 00 ........"
- }
- @{
- Name = "Can process char type 'fhx -InputObject ([char]`'A`')'"
- InputObject = [char]'A'
- Count = 1
- ExpectedResult = "00000000000000000000 41 A"
- }
- @{
- Name = "Can process char[] type 'fhx -InputObject ([char[]](`'A`'))'"
- InputObject = [char[]]('A')
- Count = 1
- ExpectedResult = "00000000000000000000 41 A"
- }
- @{
- Name = "Can process char[] type 'fhx -InputObject ([char[]](`'A`', 'B'))'"
- InputObject = [char[]]('A', 'B')
- Count = 1
- ExpectedResult = "00000000000000000000 41 42 AB"
+ Name = "Can process C#-native sbyte enum array '[TestSByteEnum[]]('One', 'Two', 'Three', 'Four') | fhx'"
+ InputObject = [TestSByteEnum[]]('One', 'Two', 'Three', 'Four')
+ Count = 1
+ ExpectedResult = "0000000000000000 FF FE FD FC .þýü"
}
)
- It "" -TestCase $testCases{
+ It "" -TestCase $testCases {
param ($Name, $InputObject, $Count, $ExpectedResult)
@@ -150,120 +144,167 @@ Describe "FormatHex" -tags "CI" {
}
Context "InputObject From Pipeline" {
+ BeforeAll {
+ enum TestEnum {
+ TestOne = 1; TestTwo = 2; TestThree = 3; TestFour = 4
+ }
+ Add-Type -TypeDefinition @'
+public enum TestSByteEnum : sbyte {
+ One = -1,
+ Two = -2,
+ Three = -3,
+ Four = -4
+}
+'@
+ }
+
$testCases = @(
@{
- Name = "Can process byte type '[byte]5 | fhx'"
- InputObject = [byte]5
- Count = 1
- ExpectedResult = "00000000000000000000 05"
+ Name = "Can process byte type '[byte]5 | fhx'"
+ InputObject = [byte]5
+ Count = 1
+ ExpectedResult = "0000000000000000 05"
}
@{
- Name = "Can process byte[] type '[byte[]](1,2) | fhx'"
- InputObject = [byte[]](1,2)
- Count = 2
- ExpectedResult = "00000000000000000000 01 ."
- ExpectedSecondResult = "00000000000000000000 02 ."
+ Name = "Can process byte[] type '[byte[]](1,2) | fhx'"
+ InputObject = [byte[]](1, 2)
+ Count = 1
+ ExpectedResult = "0000000000000000 01 02 ��"
}
@{
- Name = "Can process int type '7 | fhx'"
- InputObject = 7
- Count = 1
- ExpectedResult = "00000000000000000000 07 00 00 00 ...."
+ Name = "Can process int type '7 | fhx'"
+ InputObject = 7
+ Count = 1
+ ExpectedResult = "0000000000000000 07 00 00 00 � "
}
@{
- Name = "Can process int[] type '[int[]](5,6) | fhx'"
- InputObject = [int[]](5,6)
- Count = 2
- ExpectedResult = "00000000000000000000 05 00 00 00 ...."
- ExpectedSecondResult = "00000000000000000000 06 00 00 00 ...."
+ Name = "Can process int[] type '[int[]](5,6) | fhx'"
+ InputObject = [int[]](5, 6)
+ Count = 1
+ ExpectedResult = "0000000000000000 05 00 00 00 06 00 00 00 � � "
}
@{
- Name = "Can process int32 type '[int32]2032 | fhx'"
- InputObject = [int32]2032
- Count = 1
- ExpectedResult = "00000000000000000000 F0 07 00 00 ð..."
+ Name = "Can process int32 type '[int32]2032 | fhx'"
+ InputObject = [int32]2032
+ Count = 1
+ ExpectedResult = "0000000000000000 F0 07 00 00 ð� "
}
@{
- Name = "Can process int32[] type '[int32[]](2032, 2033) | fhx'"
- InputObject = [int32[]](2032, 2033)
- Count = 2
- ExpectedResult = "00000000000000000000 F0 07 00 00 ð..."
- ExpectedSecondResult = "00000000000000000000 F1 07 00 00 ñ..."
+ Name = "Can process int32[] type '[int32[]](2032, 2033) | fhx'"
+ InputObject = [int32[]](2032, 2033)
+ Count = 1
+ ExpectedResult = "0000000000000000 F0 07 00 00 F1 07 00 00 ð� ñ� "
}
@{
- Name = "Can process Int64 type '[Int64]9223372036854775807 | fhx'"
- InputObject = [Int64]9223372036854775807
- Count = 1
- ExpectedResult = "00000000000000000000 FF FF FF FF FF FF FF 7F ......."
+ Name = "Can process Int64 type '[Int64]9223372036854775807 | fhx'"
+ InputObject = [Int64]9223372036854775807
+ Count = 1
+ ExpectedResult = "0000000000000000 FF FF FF FF FF FF FF 7F ÿÿÿÿÿÿÿ�"
}
@{
- Name = "Can process Int64[] type '[Int64[]](9223372036852,9223372036853) | fhx'"
- InputObject = [Int64[]](9223372036852,9223372036853)
- Count = 2
- ExpectedResult = "00000000000000000000 F4 5A D0 7B 63 08 00 00 ôZÐ{c..."
- ExpectedSecondResult = "00000000000000000000 F5 5A D0 7B 63 08 00 00 õZÐ{c..."
+ Name = "Can process Int64[] type '[Int64[]](9223372036852,9223372036853) | fhx'"
+ InputObject = [Int64[]](9223372036852, 9223372036853)
+ Count = 1
+ ExpectedResult = "0000000000000000 F4 5A D0 7B 63 08 00 00 F5 5A D0 7B 63 08 00 00 ôZÐ{c� õZÐ{c� "
}
@{
- Name = "Can process string type 'hello world | fhx'"
- InputObject = "hello world"
- Count = 1
- ExpectedResult = "00000000000000000000 68 65 6C 6C 6F 20 77 6F 72 6C 64 hello world"
+ Name = "Can process string type 'hello world | fhx'"
+ InputObject = "hello world"
+ Count = 1
+ ExpectedResult = "0000000000000000 68 65 6C 6C 6F 20 77 6F 72 6C 64 hello world"
}
@{
- Name = "Can process enum type '[DisplayHintType]::DateTime | fhx"
- InputObject = [Microsoft.PowerShell.Commands.DisplayHintType]::DateTime
- Count = 1
- ExpectedResult = "00000000000000000000 02 00 00 00 ...."
+ Name = "Can process string type amidst other types { 1, 2, 3, 'hello world' | fhx }"
+ InputObject = 1, 2, 3, "hello world"
+ Count = 2
+ ExpectedResult = "0000000000000000 01 00 00 00 02 00 00 00 03 00 00 00 � � � "
+ ExpectedSecondResult = "0000000000000000 68 65 6C 6C 6F 20 77 6F 72 6C 64 hello world"
}
@{
- Name = "Can process DisplayHintType[] type '[DisplayHintType[]](DateTime) | fhx'"
- InputObject = [Microsoft.PowerShell.Commands.DisplayHintType[]]([Microsoft.PowerShell.Commands.DisplayHintType]::DateTime)
- Count = 1
- ExpectedResult = "00000000000000000000 02 00 00 00 ...."
+ Name = "Can process jagged array type '[sbyte[]](-15, 18, 21, -5), [byte[]](1, 2, 3, 4, 5, 6) | fhx'"
+ InputObject = [sbyte[]](-15, 18, 21, -5), [byte[]](1, 2, 3, 4, 5, 6)
+ Count = 2
+ ExpectedResult = "0000000000000000 F1 12 15 FB ñ��û"
+ ExpectedSecondResult = "0000000000000000 01 02 03 04 05 06 ������"
}
@{
- Name = "Can process DisplayHintType[] type '[DisplayHintType[]](DateTime, Time) | fhx'"
- InputObject = [Microsoft.PowerShell.Commands.DisplayHintType[]]([Microsoft.PowerShell.Commands.DisplayHintType]::DateTime, [Microsoft.PowerShell.Commands.DisplayHintType]::Time)
- Count = 2
- ExpectedResult = "00000000000000000000 02 00 00 00 ...."
- ExpectedSecondResult = "00000000000000000000 01 00 00 00 ...."
+ Name = "Can process PS-native enum array '[TestEnum[]]('TestOne', 'TestTwo', 'TestThree', 'TestFour') | fhx'"
+ InputObject = [TestEnum[]]('TestOne', 'TestTwo', 'TestThree', 'TestFour')
+ Count = 1
+ ExpectedResult = "0000000000000000 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 � � � � "
}
@{
- Name = "Can process char type '[char]`'A`' | fhx'"
- InputObject = [char]'A'
- Count = 1
- ExpectedResult = "00000000000000000000 41 A"
- }
- @{
- Name = "Can process char[] type '[char[]](`'A`') | fhx'"
- InputObject = [char[]]('A')
- Count = 1
- ExpectedResult = "00000000000000000000 41 A"
- }
- @{
- Name = "Can process char[] type '[char[]](`'A`', 'B') | fhx'"
- InputObject = [char[]]('A', 'B')
- Count = 2
- ExpectedResult = "00000000000000000000 41 A"
- ExpectedSecondResult = "00000000000000000000 42 B"
+ Name = "Can process C#-native sbyte enum array '[TestSByteEnum[]]('One', 'Two', 'Three', 'Four') | fhx'"
+ InputObject = [TestSByteEnum[]]('One', 'Two', 'Three', 'Four')
+ Count = 1
+ ExpectedResult = "0000000000000000 FF FE FD FC ÿþýü"
}
)
- It "" -Testcase $testCases {
+ It "" -TestCases $testCases {
param ($Name, $InputObject, $Count, $ExpectedResult, $ExpectedSecondResult)
$result = $InputObject | Format-Hex
- $result.count | Should -Be $Count
+ $result.Count | Should -Be $Count
$result | Should -BeOfType 'Microsoft.PowerShell.Commands.ByteCollection'
$result[0].ToString() | Should -MatchExactly $ExpectedResult
- if ($result.count -gt 1)
- {
+ if ($result.count -gt 1) {
$result[1].ToString() | Should -MatchExactly $ExpectedSecondResult
}
}
+
+ $heterogenousInputCases = @(
+ @{
+ InputScript = { [sbyte[]](-15, 18, 21, -5), "hello", [byte[]](1..6), 1, 2, 3, 4 }
+ Count = 4
+ ExpectedResults = @(
+ "0000000000000000 F1 12 15 FB ñ��û"
+ "0000000000000000 68 65 6C 6C 6F hello"
+ "0000000000000000 01 02 03 04 05 06 ������"
+ "0000000000000000 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 � � � � "
+ )
+ ExpectedLabels = @(
+ "System.SByte[]"
+ "System.String"
+ "System.Byte"
+ "System.Int32"
+ ).ForEach{ [regex]::Escape($_) } -join '|'
+ }
+ @{
+ InputScript = { $inputFile1, "Mountains are merely mountains", 1, 4, 5, 3, [ushort[]](1..10) }
+ Count = 6
+ ExpectedResults = @(
+ "0000000000000000 48 65 6C 6C 6F 20 57 6F 72 6C 64 Hello World"
+ "0000000000000000 4D 6F 75 6E 74 61 69 6E 73 20 61 72 65 20 6D 65 Mountains are me"
+ "0000000000000010 72 65 6C 79 20 6D 6F 75 6E 74 61 69 6E 73 rely mountains"
+ "0000000000000000 01 00 00 00 04 00 00 00 05 00 00 00 03 00 00 00 � � � � "
+ "0000000000000000 01 00 02 00 03 00 04 00 05 00 06 00 07 00 08 00 � � � � � � � � "
+ "0000000000000010 09 00 0A 00 � � "
+ )
+ ExpectedLabels = @(
+ $inputFile1.FullName
+ "System.String"
+ "System.Int32"
+ "System.UInt16[]"
+ ).ForEach{ [regex]::Escape($_) } -join '|'
+ }
+ )
+
+ It 'can process jagged input: ' -TestCases $heterogenousInputCases {
+ param($InputScript, $Count, $ExpectedResults, $ExpectedLabels)
+
+ $Results = & $InputScript | Format-Hex
+ $Results | Should -HaveCount $Count
+ $ExpectedResults | Should -HaveCount $Count
+
+ for ($Number = 0; $Number -lt $Results.Count; $Number++) {
+ $Results[$Number] | Should -MatchExactly $ExpectedResults[$Number]
+ $Results[$Number].Label | Should -MatchExactly $ExpectedLabels
+ }
+ }
}
Context "Path and LiteralPath Parameters" {
@@ -272,39 +313,39 @@ Describe "FormatHex" -tags "CI" {
$testCases = @(
@{
- Name = "Can process file content from given file path 'fhx -Path `$inputFile1'"
- PathCase = $true
- Path = $inputFile1
- Count = 1
+ Name = "Can process file content from given file path 'fhx -Path `$inputFile1'"
+ PathCase = $true
+ Path = $inputFile1
+ Count = 1
ExpectedResult = $inputText1
}
@{
- Name = "Can process file content from all files in array of file paths 'fhx -Path `$inputFile1, `$inputFile2'"
- PathCase = $true
- Path = @($inputFile1, $inputFile2)
- Count = 2
- ExpectedResult = $inputText1
+ Name = "Can process file content from all files in array of file paths 'fhx -Path `$inputFile1, `$inputFile2'"
+ PathCase = $true
+ Path = @($inputFile1, $inputFile2)
+ Count = 2
+ ExpectedResult = $inputText1
ExpectedSecondResult = $inputText2
}
@{
- Name = "Can process file content from all files when resolved to multiple paths 'fhx -Path '`$testDirectory\SourceFile-*''"
- PathCase = $true
- Path = "$testDirectory\SourceFile-*"
- Count = 2
- ExpectedResult = $inputText1
+ Name = "Can process file content from all files when resolved to multiple paths 'fhx -Path '`$testDirectory\SourceFile-*''"
+ PathCase = $true
+ Path = "$testDirectory\SourceFile-*"
+ Count = 2
+ ExpectedResult = $inputText1
ExpectedSecondResult = $inputText2
}
@{
- Name = "Can process file content from given file path 'fhx -LiteralPath `$inputFile3'"
- Path = $inputFile3
- Count = 1
+ Name = "Can process file content from given file path 'fhx -LiteralPath `$inputFile3'"
+ Path = $inputFile3
+ Count = 1
ExpectedResult = $inputText3
}
@{
- Name = "Can process file content from all files in array of file paths 'fhx -LiteralPath `$inputFile1, `$inputFile3'"
- Path = @($inputFile1, $inputFile3)
- Count = 2
- ExpectedResult = $inputText1
+ Name = "Can process file content from all files in array of file paths 'fhx -LiteralPath `$inputFile1, `$inputFile3'"
+ Path = @($inputFile1, $inputFile3)
+ Count = 2
+ ExpectedResult = $inputText1
ExpectedSecondResult = $inputText3
}
)
@@ -313,62 +354,78 @@ Describe "FormatHex" -tags "CI" {
param ($Name, $PathCase, $Path, $ExpectedResult, $ExpectedSecondResult)
- if ($PathCase)
- {
- $result = Format-Hex -Path $Path
+ if ($PathCase) {
+ $result = Format-Hex -Path $Path
}
- else # LiteralPath
- {
+ else {
+ # LiteralPath
$result = Format-Hex -LiteralPath $Path
}
$result | Should -BeOfType 'Microsoft.PowerShell.Commands.ByteCollection'
$result[0].ToString() | Should -MatchExactly $ExpectedResult
- if ($result.count -gt 1)
- {
+ if ($result.count -gt 1) {
$result[1].ToString() | Should -MatchExactly $ExpectedSecondResult
}
}
+
+ It 'properly accepts -LiteralPath input from a FileInfo object' {
+ $FilePath = 'TestDrive:\FHX-LitPathTest.txt'
+ "Hello World!" | Set-Content -Path $FilePath
+ $FileObject = Get-Item -Path $FilePath
+
+ $result = $FileObject | Format-Hex
+ if ($IsWindows) {
+ $Result.Bytes[-1] | Should -Be 0x0A
+ $Result.Bytes[-2] | Should -Be 0x0D
+ $Result.Bytes.Length | Should -Be 14
+ }
+ else {
+ $Result.Bytes[-1] | Should -Be 0x0A
+ $Result.Bytes.Length | Should -Be 13
+ }
+ }
}
Context "Encoding Parameter" {
$testCases = @(
@{
- Name = "Can process ASCII encoding 'fhx -InputObject 'hello' -Encoding ASCII'"
- Encoding = "ASCII"
- Count = 1
- ExpectedResult = "00000000000000000000 68 65 6C 6C 6F hello"
+ Name = "Can process ASCII encoding 'fhx -InputObject 'hello' -Encoding ASCII'"
+ Encoding = "ASCII"
+ Count = 1
+ ExpectedResult = "0000000000000000 68 65 6C 6C 6F hello"
}
@{
- Name = "Can process BigEndianUnicode encoding 'fhx -InputObject 'hello' -Encoding BigEndianUnicode'"
- Encoding = "BigEndianUnicode"
- Count = 1
- ExpectedResult = "00000000000000000000 00 68 00 65 00 6C 00 6C 00 6F .h.e.l.l.o"
+ Name = "Can process BigEndianUnicode encoding 'fhx -InputObject 'hello' -Encoding BigEndianUnicode'"
+ Encoding = "BigEndianUnicode"
+ Count = 1
+ ExpectedResult = "0000000000000000 00 68 00 65 00 6C 00 6C 00 6F h e l l o"
}
@{
- Name = "Can process Unicode encoding 'fhx -InputObject 'hello' -Encoding Unicode'"
- Encoding = "Unicode"
- Count = 1
- ExpectedResult = "00000000000000000000 68 00 65 00 6C 00 6C 00 6F 00 h.e.l.l.o."
+ Name = "Can process Unicode encoding 'fhx -InputObject 'hello' -Encoding Unicode'"
+ Encoding = "Unicode"
+ Count = 1
+ ExpectedResult = "0000000000000000 68 00 65 00 6C 00 6C 00 6F 00 h e l l o "
}
@{
- Name = "Can process UTF7 encoding 'fhx -InputObject 'hello' -Encoding UTF7'"
- Encoding = "UTF7"
- Count = 1
- ExpectedResult = "00000000000000000000 68 65 6C 6C 6F hello"
+ Name = "Can process UTF7 encoding 'fhx -InputObject 'hello' -Encoding UTF7'"
+ Encoding = "UTF7"
+ Count = 1
+ ExpectedResult = "0000000000000000 68 65 6C 6C 6F hello"
}
- @{
- Name = "Can process UTF8 encoding 'fhx -InputObject 'hello' -Encoding UTF8'"
- Encoding = "UTF8"
- Count = 1
- ExpectedResult = "00000000000000000000 68 65 6C 6C 6F hello"
+ @{
+ Name = "Can process UTF8 encoding 'fhx -InputObject 'hello' -Encoding UTF8'"
+ Encoding = "UTF8"
+ Count = 1
+ ExpectedResult = "0000000000000000 68 65 6C 6C 6F hello"
}
- @{
- Name = "Can process UTF32 encoding 'fhx -InputObject 'hello' -Encoding UTF32'"
- Encoding = "UTF32"
- Count = 1
- ExpectedResult = "00000000000000000000 68 00 00 00 65 00 00 00 6C 00 00 00 6C 00 00 00 h...e...l...l...$($newline)00000000000000000010 6F 00 00 00 o..."
+ @{
+ Name = "Can process UTF32 encoding 'fhx -InputObject 'hello' -Encoding UTF32'"
+ Encoding = "UTF32"
+ Count = 2
+ ExpectedResult = "0000000000000000 68 00 00 00 65 00 00 00 6C 00 00 00 6C 00 00 00 h e l l "
+ ExpectedSecondResult = "0000000000000010 6F 00 00 00 o "
}
)
@@ -390,16 +447,16 @@ Describe "FormatHex" -tags "CI" {
$testCases = @(
@{
- Name = "Does not support non-FileSystem Provider paths 'fhx -Path 'Cert:\CurrentUser\My\`$thumbprint' -ErrorAction Stop'"
- PathParameterErrorCase = $true
- Path = "Cert:\CurrentUser\My\$thumbprint"
+ Name = "Does not support non-FileSystem Provider paths 'fhx -Path 'Cert:\CurrentUser\My\`$thumbprint' -ErrorAction Stop'"
+ PathParameterErrorCase = $true
+ Path = "Cert:\CurrentUser\My\$thumbprint"
ExpectedFullyQualifiedErrorId = "FormatHexOnlySupportsFileSystemPaths,Microsoft.PowerShell.Commands.FormatHex"
}
@{
- Name = "Type Not Supported 'fhx -InputObject @{'hash' = 'table'} -ErrorAction Stop'"
- InputObjectErrorCase = $true
- Path = $inputFile1
- InputObject = @{ "hash" = "table" }
+ Name = "Type Not Supported 'fhx -InputObject @{'hash' = 'table'} -ErrorAction Stop'"
+ InputObjectErrorCase = $true
+ Path = $inputFile1
+ InputObject = @{ "hash" = "table" }
ExpectedFullyQualifiedErrorId = "FormatHexTypeNotSupported,Microsoft.PowerShell.Commands.FormatHex"
}
)
@@ -409,12 +466,10 @@ Describe "FormatHex" -tags "CI" {
param ($Name, $PathParameterErrorCase, $Path, $InputObject, $InputObjectErrorCase, $ExpectedFullyQualifiedErrorId)
{
- if ($PathParameterErrorCase)
- {
+ if ($PathParameterErrorCase) {
$result = Format-Hex -Path $Path -ErrorAction Stop
}
- if ($InputObjectErrorCase)
- {
+ if ($InputObjectErrorCase) {
$result = Format-Hex -InputObject $InputObject -ErrorAction Stop
}
} | Should -Throw -ErrorId $ExpectedFullyQualifiedErrorId
@@ -425,20 +480,20 @@ Describe "FormatHex" -tags "CI" {
$testCases = @(
@{
- Name = "If given invalid path in array, continues to process valid paths 'fhx -Path `$invalidPath, `$inputFile1 -ErrorVariable e -ErrorAction SilentlyContinue'"
- PathCase = $true
- InvalidPath = "$($inputFile1.DirectoryName)\fakefile8888845345345348709.txt"
+ Name = "If given invalid path in array, continues to process valid paths 'fhx -Path `$invalidPath, `$inputFile1 -ErrorVariable e -ErrorAction SilentlyContinue'"
+ PathCase = $true
+ InvalidPath = "$($inputFile1.DirectoryName)\fakefile8888845345345348709.txt"
ExpectedFullyQualifiedErrorId = "FileNotFound,Microsoft.PowerShell.Commands.FormatHex"
}
@{
- Name = "If given a non FileSystem path in array, continues to process valid paths 'fhx -Path `$invalidPath, `$inputFile1 -ErrorVariable e -ErrorAction SilentlyContinue'"
- PathCase = $true
- InvalidPath = "Cert:\CurrentUser\My\$thumbprint"
+ Name = "If given a non FileSystem path in array, continues to process valid paths 'fhx -Path `$invalidPath, `$inputFile1 -ErrorVariable e -ErrorAction SilentlyContinue'"
+ PathCase = $true
+ InvalidPath = "Cert:\CurrentUser\My\$thumbprint"
ExpectedFullyQualifiedErrorId = "FormatHexOnlySupportsFileSystemPaths,Microsoft.PowerShell.Commands.FormatHex"
}
@{
- Name = "If given a non FileSystem path in array (with LiteralPath), continues to process valid paths 'fhx -Path `$invalidPath, `$inputFile1 -ErrorVariable e -ErrorAction SilentlyContinue'"
- InvalidPath = "Cert:\CurrentUser\My\$thumbprint"
+ Name = "If given a non FileSystem path in array (with LiteralPath), continues to process valid paths 'fhx -Path `$invalidPath, `$inputFile1 -ErrorVariable e -ErrorAction SilentlyContinue'"
+ InvalidPath = "Cert:\CurrentUser\My\$thumbprint"
ExpectedFullyQualifiedErrorId = "FormatHexOnlySupportsFileSystemPaths,Microsoft.PowerShell.Commands.FormatHex"
}
)
@@ -450,12 +505,11 @@ Describe "FormatHex" -tags "CI" {
$output = $null
$errorThrown = $null
- if ($PathCase)
- {
+ if ($PathCase) {
$output = Format-Hex -Path $InvalidPath, $inputFile1 -ErrorVariable errorThrown -ErrorAction SilentlyContinue
}
- else # LiteralPath
- {
+ else {
+ # LiteralPath
$output = Format-Hex -LiteralPath $InvalidPath, $inputFile1 -ErrorVariable errorThrown -ErrorAction SilentlyContinue
}
@@ -470,10 +524,10 @@ Describe "FormatHex" -tags "CI" {
It "Path is default Parameter Set 'fhx `$inputFile1'" {
- $result = Format-Hex $inputFile1
+ $result = Format-Hex $inputFile1
$result | Should -Not -BeNullOrEmpty
- ,$result | Should -BeOfType 'Microsoft.PowerShell.Commands.ByteCollection'
+ , $result | Should -BeOfType 'Microsoft.PowerShell.Commands.ByteCollection'
$actualResult = $result.ToString()
$actualResult | Should -MatchExactly $inputText1
}
@@ -483,7 +537,7 @@ Describe "FormatHex" -tags "CI" {
$result = Get-ChildItem $inputFile1 | Format-Hex
$result | Should -Not -BeNullOrEmpty
- ,$result | Should -BeOfType 'Microsoft.PowerShell.Commands.ByteCollection'
+ , $result | Should -BeOfType 'Microsoft.PowerShell.Commands.ByteCollection'
$actualResult = $result.ToString()
$actualResult | Should -MatchExactly $inputText1
}
@@ -493,8 +547,9 @@ Describe "FormatHex" -tags "CI" {
$result = "a" * 30 | Format-Hex
$result | Should -Not -BeNullOrEmpty
- ,$result | Should -BeOfType 'Microsoft.PowerShell.Commands.ByteCollection'
- $result.ToString() | Should -MatchExactly "00000000000000000000 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 aaaaaaaaaaaaaaaa$($newline)00000000000000000010 61 61 61 61 61 61 61 61 61 61 61 61 61 61 aaaaaaaaaaaaaa "
+ $result | Should -BeOfType 'Microsoft.PowerShell.Commands.ByteCollection'
+ $result[0].ToString() | Should -MatchExactly "0000000000000000 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 aaaaaaaaaaaaaaaa"
+ $result[1].ToString() | Should -MatchExactly "0000000000000010 61 61 61 61 61 61 61 61 61 61 61 61 61 61 aaaaaaaaaaaaaa "
}
It "Validate that files do not have buffer underrun problems 'Format-Hex -Path `$InputFile4'" {
@@ -503,9 +558,9 @@ Describe "FormatHex" -tags "CI" {
$result | Should -Not -BeNullOrEmpty
$result.Count | Should -Be 3
- $result[0].ToString() | Should -MatchExactly "00000000000000000000 4E 6F 77 20 69 73 20 74 68 65 20 77 69 6E 74 65 Now is the winte"
- $result[1].ToString() | Should -MatchExactly "00000000000000000010 72 20 6F 66 20 6F 75 72 20 64 69 73 63 6F 6E 74 r of our discont"
- $result[2].ToString() | Should -MatchExactly "00000000000000000020 65 6E 74 ent "
+ $result[0].ToString() | Should -MatchExactly "0000000000000000 4E 6F 77 20 69 73 20 74 68 65 20 77 69 6E 74 65 Now is the winte"
+ $result[1].ToString() | Should -MatchExactly "0000000000000010 72 20 6F 66 20 6F 75 72 20 64 69 73 63 6F 6E 74 r of our discont"
+ $result[2].ToString() | Should -MatchExactly "0000000000000020 65 6E 74 ent "
}
}
@@ -516,23 +571,22 @@ Describe "FormatHex" -tags "CI" {
$result | Should -Not -BeNullOrEmpty
$result.Count | Should -Be 3
- $result[0].ToString() | Should -MatchExactly "00000000000000000000 4E 6F 77 20 69 73 20 74 68 65 20 77 69 6E 74 65 Now is the winte"
- $result[1].ToString() | Should -MatchExactly "00000000000000000010 72 20 6F 66 20 6F 75 72 20 64 69 73 63 6F 6E 74 r of our discont"
- $result[2].ToString() | Should -MatchExactly "00000000000000000020 65 6E 74 ent "
+ $result[0].ToString() | Should -MatchExactly "0000000000000000 4E 6F 77 20 69 73 20 74 68 65 20 77 69 6E 74 65 Now is the winte"
+ $result[1].ToString() | Should -MatchExactly "0000000000000010 72 20 6F 66 20 6F 75 72 20 64 69 73 63 6F 6E 74 r of our discont"
+ $result[2].ToString() | Should -MatchExactly "0000000000000020 65 6E 74 ent "
}
It "Count = 1" {
$result = Format-Hex -Path $inputFile4 -Count 1
- $result.ToString() | Should -MatchExactly "00000000000000000000 4E N "
+ $result.ToString() | Should -MatchExactly "0000000000000000 4E N "
}
It "Offset = length" {
-
$result = Format-Hex -Path $InputFile4 -Offset $inputText4.Length
$result | Should -BeNullOrEmpty
$result = Format-Hex -InputObject $inputText4 -Offset $inputText4.Length
- $result.Bytes | Should -HaveCount 0
+ $result | Should -BeNullOrEmpty
}
It "Offset = 1" {
@@ -541,14 +595,14 @@ Describe "FormatHex" -tags "CI" {
$result | Should -Not -BeNullOrEmpty
$result.Count | Should -Be 3
- $result[0].ToString() | Should -MatchExactly "00000000000000000001 6F 77 20 69 73 20 74 68 65 20 77 69 6E 74 65 72 ow is the winter"
- $result[1].ToString() | Should -MatchExactly "00000000000000000011 20 6F 66 20 6F 75 72 20 64 69 73 63 6F 6E 74 65 of our disconte"
- $result[2].ToString() | Should -MatchExactly "00000000000000000021 6E 74 nt "
+ $result[0].ToString() | Should -MatchExactly "0000000000000001 6F 77 20 69 73 20 74 68 65 20 77 69 6E 74 65 72 ow is the winter"
+ $result[1].ToString() | Should -MatchExactly "0000000000000011 20 6F 66 20 6F 75 72 20 64 69 73 63 6F 6E 74 65 of our disconte"
+ $result[2].ToString() | Should -MatchExactly "0000000000000021 6E 74 nt "
}
It "Count = 1 and Offset = 1" {
$result = Format-Hex -Path $inputFile4 -Count 1 -Offset 1
- $result.ToString() | Should -MatchExactly "00000000000000000001 6F o "
+ $result.ToString() | Should -MatchExactly "0000000000000001 6F o "
}
It "Count should be > 0" {
@@ -565,9 +619,9 @@ Describe "FormatHex" -tags "CI" {
$result | Should -Not -BeNullOrEmpty
$result.Count | Should -Be 3
- $result[0].ToString() | Should -MatchExactly "00000000000000000000 4E 6F 77 20 69 73 20 74 68 65 20 77 69 6E 74 65 Now is the winte"
- $result[1].ToString() | Should -MatchExactly "00000000000000000010 72 20 6F 66 20 6F 75 72 20 64 69 73 63 6F 6E 74 r of our discont"
- $result[2].ToString() | Should -MatchExactly "00000000000000000020 65 6E 74 ent "
+ $result[0].ToString() | Should -MatchExactly "0000000000000000 4E 6F 77 20 69 73 20 74 68 65 20 77 69 6E 74 65 Now is the winte"
+ $result[1].ToString() | Should -MatchExactly "0000000000000010 72 20 6F 66 20 6F 75 72 20 64 69 73 63 6F 6E 74 r of our discont"
+ $result[2].ToString() | Should -MatchExactly "0000000000000020 65 6E 74 ent "
}
}
}