diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/XmlCommands.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/XmlCommands.cs
index 71dfd9e275..2a9263060b 100644
--- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/XmlCommands.cs
+++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/XmlCommands.cs
@@ -240,12 +240,6 @@ namespace Microsoft.PowerShell.Commands
_fs.Dispose();
_fs = null;
}
- // reset the read-only attribute
- if (null != _readOnlyFileInfo)
- {
- _readOnlyFileInfo.Attributes |= FileAttributes.ReadOnly;
- _readOnlyFileInfo = null;
- }
}
#endregion file
@@ -572,11 +566,11 @@ namespace Microsoft.PowerShell.Commands
if (Depth == 0)
{
- _serializer = new CustomSerialization(_xw, _notypeinformation);
+ _serializer = new CustomSerialization(_xw, NoTypeInformation);
}
else
{
- _serializer = new CustomSerialization(_xw, _notypeinformation, Depth);
+ _serializer = new CustomSerialization(_xw, NoTypeInformation, Depth);
}
}
@@ -645,14 +639,8 @@ namespace Microsoft.PowerShell.Commands
internal ImportXmlHelper(string fileName, PSCmdlet cmdlet, bool isLiteralPath)
{
- if (fileName == null)
- {
- throw PSTraceSource.NewArgumentNullException("fileName");
- }
- if (cmdlet == null)
- {
- throw PSTraceSource.NewArgumentNullException("cmdlet");
- }
+ Dbg.Assert(fileName != null, "filename is mandatory");
+ Dbg.Assert(cmdlet != null, "cmdlet is mandatory");
_path = fileName;
_cmdlet = cmdlet;
_isLiteralPath = isLiteralPath;
@@ -749,17 +737,10 @@ namespace Microsoft.PowerShell.Commands
// if paging is not specified then keep the old V2 behavior
if (skip == 0 && first == ulong.MaxValue)
{
- ulong item = 0;
while (!_deserializer.Done())
{
object result = _deserializer.Deserialize();
- if (item++ < skip)
- continue;
- if (first == 0)
- break;
-
_cmdlet.WriteObject(result);
- first--;
}
}
// else try to flatten the output if possible
@@ -772,36 +753,38 @@ namespace Microsoft.PowerShell.Commands
object result = _deserializer.Deserialize();
PSObject psObject = result as PSObject;
- if (psObject == null && skipped++ >= skip)
+ if (psObject != null)
+ {
+ ICollection c = psObject.BaseObject as ICollection;
+ if (c != null)
+ {
+ foreach (object o in c)
+ {
+ if (count >= first)
+ break;
+
+ if (skipped++ >= skip)
+ {
+ count++;
+ _cmdlet.WriteObject(o);
+ }
+ }
+ }
+ else
+ {
+ if (skipped++ >= skip)
+ {
+ count++;
+ _cmdlet.WriteObject(result);
+ }
+ }
+ }
+ else if (skipped++ >= skip)
{
count++;
_cmdlet.WriteObject(result);
continue;
}
-
- ICollection c = psObject.BaseObject as ICollection;
- if (c != null)
- {
- foreach (object o in c)
- {
- if (count >= first)
- break;
-
- if (skipped++ >= skip)
- {
- count++;
- _cmdlet.WriteObject(o);
- }
- }
- }
- else
- {
- if (skipped++ >= skip)
- {
- count++;
- _cmdlet.WriteObject(result);
- }
- }
}
}
}
diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Xml.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Xml.Tests.ps1
index fab41749a4..08a1387fa9 100644
--- a/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Xml.Tests.ps1
+++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Xml.Tests.ps1
@@ -49,5 +49,24 @@
$expectedValue = ''
$returnObject.OuterXml | Should Be $expectedValue
}
+
+ It "StopProcessing should work" {
+ $ps = [PowerShell]::Create()
+ $ps.AddCommand("Get-Process")
+ $ps.AddCommand("ConvertTo-Xml")
+ $ps.AddParameter("Depth", 2)
+ $ps.BeginInvoke()
+ $ps.Stop()
+ $ps.InvocationStateInfo.State | Should Be "Stopped"
+ }
+
+ # these tests just cover aspects that aren't normally exercised being used as a cmdlet
+ It "Can read back switch and parameter values using api" {
+ Add-Type -AssemblyName "${pshome}/Microsoft.PowerShell.Commands.Utility.dll"
+
+ $cmd = [Microsoft.PowerShell.Commands.ConvertToXmlCommand]::new()
+ $cmd.NoTypeInformation = $true
+ $cmd.NoTypeInformation | Should Be $true
+ }
}
diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/XMLCommand.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/XMLCommand.Tests.ps1
index 310d7dd003..e5c1de69ca 100644
--- a/test/powershell/Modules/Microsoft.PowerShell.Utility/XMLCommand.Tests.ps1
+++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/XMLCommand.Tests.ps1
@@ -30,17 +30,17 @@ Describe "XmlCommand DRT basic functionality Tests" -Tags "CI" {
}
AfterEach {
- remove-item $testfile
+ remove-item $testfile -Force -ErrorAction SilentlyContinue
}
- It "Import with CliXml directive should work" -Skip:$IsOSX{
- Get-Process | Export-Clixml $testfile
+ It "Import with CliXml directive should work" {
+ Get-Command export* -Type Cmdlet | Select-Object -First 3 | Export-Clixml -Path $testfile
$results = Import-Clixml $testfile
- $results.Count | Should BeGreaterThan 0
- $results[0].ToString() | Should Match "System.Diagnostics.Process"
+ $results.Count | Should BeExactly 3
+ $results[0].PSTypeNames[0] | Should Be "Deserialized.System.Management.Automation.CmdletInfo"
}
- It "Import with Rehydration should work" -Skip:$IsOSX{
+ It "Import with Rehydration should work" {
$property1 = 256
$property2 = "abcdef"
$isHiddenTestType = [IsHiddenTestType]::New($property1,$property2)
@@ -49,4 +49,112 @@ Describe "XmlCommand DRT basic functionality Tests" -Tags "CI" {
$results.Property1 | Should Be $property1
$results.Property2 | Should Be $property2
}
+
+ It "Export-Clixml StopProcessing should succeed" {
+ $ps = [PowerShell]::Create()
+ $null = $ps.AddScript("1..10")
+ $null = $ps.AddCommand("foreach-object")
+ $null = $ps.AddParameter("Process", { $_; start-sleep 1 })
+ $null = $ps.AddCommand("Export-CliXml")
+ $null = $ps.AddParameter("Path", $testfile)
+ $null = $ps.BeginInvoke()
+ Start-Sleep 1
+ $null = $ps.Stop()
+ $ps.InvocationStateInfo.State | should be "Stopped"
+ $ps.Dispose()
+ }
+
+ It "Import-Clixml StopProcessing should succeed" {
+ 1,2,3 | Export-Clixml -Path $testfile
+ $ps = [PowerShell]::Create()
+ $ps.AddCommand("Get-Process")
+ $ps.AddCommand("Import-CliXml")
+ $ps.AddParameter("Path", $testfile)
+ $ps.BeginInvoke()
+ $ps.Stop()
+ $ps.InvocationStateInfo.State | Should Be "Stopped"
+ }
+
+ It "Export-Clixml using -Depth should work" {
+ class Three
+ {
+ [int] $num = 3;
+ }
+
+ class Two
+ {
+ [Three] $three = [Three]::New();
+ [int] $value = 2;
+ }
+
+ class One
+ {
+ [Two] $two = [Two]::New();
+ [int] $value = 1;
+ }
+
+ $one = [One]::New()
+ $one | Export-Clixml -Depth 2 -Path $testfile
+ $deserialized_one = Import-Clixml -Path $testfile
+ $deserialized_one.Value | Should Be 1
+ $deserialized_one.two.Value | Should Be 2
+ $deserialized_one.two.Three | Should Not BeNullOrEmpty
+ $deserialized_one.two.three.num | Should BeNullOrEmpty
+ }
+
+ It "Import-Clixml should work with XML serialization from powershell.exe" {
+ # need to create separate process so that current powershell doesn't interpret clixml output
+ Start-Process -FilePath $pshome\powershell -RedirectStandardOutput $testfile -Args "-noprofile -nologo -outputformat xml -command get-command import-clixml" -Wait
+ $out = Import-Clixml -Path $testfile
+ $out.Name | Should Be "Import-CliXml"
+ $out.CommandType.ToString() | Should Be "Cmdlet"
+ $out.Source | Should Be "Microsoft.PowerShell.Utility"
+ }
+
+ It "Import-Clixml -IncludeTotalCount always returns unknown total count" {
+ # this cmdlets supports paging, but not this switch
+ [PSCustomObject]@{foo=1;bar=@{hello="world"}} | Export-Clixml -Path $testfile
+ $out = Import-Clixml -Path $testfile -IncludeTotalCount
+ $out[0].ToString() | Should BeExactly "Unknown total count"
+ }
+
+ It "Import-Clixml -First and -Skip work together for simple types" {
+ "one","two","three","four" | Export-Clixml -Path $testfile
+ $out = Import-Clixml -Path $testfile -First 2 -Skip 1
+ $out.Count | Should Be 2
+ $out[0] | Should BeExactly "two"
+ $out[1] | Should BeExactly "three"
+ }
+
+ It "Import-Clixml -First and -Skip work together for collections" {
+ @{a=1;b=2;c=3;d=4} | Export-Clixml -Path $testfile
+ # order not guaranteed, even with [ordered] so we have to be smart here and compare against the full result
+ $out1 = Import-Clixml -Path $testfile # this results in a hashtable
+ $out2 = Import-Clixml -Path $testfile -First 2 -Skip 1 # this results in a dictionary entry
+ $out2.Count | Should Be 2
+ ($out2.Name) -join ":" | should be (@($out1.Keys)[1, 2] -join ":")
+ ($out2.Value) -join ":" | should be (@($out1.Values)[1, 2] -join ":")
+ }
+
+ # these tests just cover aspects that aren't normally exercised being used as a cmdlet
+ It "Can read back switch and parameter values using api" {
+ Add-Type -AssemblyName "${pshome}/Microsoft.PowerShell.Commands.Utility.dll"
+
+ $cmd = [Microsoft.PowerShell.Commands.ExportClixmlCommand]::new()
+ $cmd.LiteralPath = "foo"
+ $cmd.LiteralPath | Should BeExactly "foo"
+ $cmd.NoClobber = $true
+ $cmd.NoClobber | Should Be $true
+
+ $cmd = [Microsoft.PowerShell.Commands.ImportClixmlCommand]::new()
+ $cmd.LiteralPath = "bar"
+ $cmd.LiteralPath | Should BeExactly "bar"
+
+ $cmd = [Microsoft.PowerShell.Commands.SelectXmlCommand]::new()
+ $cmd.LiteralPath = "foo"
+ $cmd.LiteralPath | Should BeExactly "foo"
+ $xml = [xml]""
+ $cmd.Xml = $xml
+ $cmd.Xml | Should Be $xml
+ }
}
diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/xml.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/xml.tests.ps1
index 8555ae4727..f0a0e1e6a7 100644
--- a/test/powershell/Modules/Microsoft.PowerShell.Utility/xml.tests.ps1
+++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/xml.tests.ps1
@@ -50,19 +50,53 @@
It $_.testName {
@(Select-XML @params).Count | Should Be 1
+ (Select-XML @params).Path | Should Be $fileName.FullName
}
}
- It "literalpath with non filesystem path" {
+ It "non filesystem path using " -TestCases @(
+ @{parameter="literalPath"},
+ @{parameter="path"}
+ ) {
+ param($parameter)
$__data = "abcdefg"
- Select-XML -literalPath variable:__data "Root" -ErrorVariable selectXmlError -ErrorAction SilentlyContinue
- $selectXmlError.FullyQualifiedErrorId | Should Be 'ProcessingFile,Microsoft.PowerShell.Commands.SelectXmlCommand'
+ $params = @{$parameter="variable:__data"}
+ { Select-XML @params "Root" | Should BeErrorId 'ProcessingFile,Microsoft.PowerShell.Commands.SelectXmlCommand' }
}
- It "path with non filesystem path" {
- $__data = "abcdefg"
- Select-XML -Path variable:\__data "Root" -ErrorVariable selectXmlError -ErrorAction SilentlyContinue
- $selectXmlError.FullyQualifiedErrorId | Should Be 'ProcessingFile,Microsoft.PowerShell.Commands.SelectXmlCommand'
+ It "Invalid xml file" {
+ $testfile = "$testdrive/test.xml"
+ Set-Content -Path $testfile -Value ""
+ { Select-Xml -Path $testfile -XPath foo | ShouldBeErrorId 'ProcessingFile,Microsoft.PowerShell.Commands.SelectXmlCommand' }
+ }
+
+ It "-xml works with inputstream" {
+ [xml]$xml = "helloworld"
+ $node = Select-Xml -Xml $xml -XPath "//c:b" -Namespace @{c='bar'}
+ $node.Path | Should BeExactly "InputStream"
+ $node.Pattern = "//c:b"
+ $node.ToString() | Should BeExactly "hello"
+ }
+
+ It "Returns error for invalid xmlnamespace" {
+ [xml]$xml = "helloworld"
+ { Select-Xml -Xml $xml -XPath foo -Namespace @{c=$null} | ShouldBeErrorId "PrefixError,Microsoft.PowerShell.Commands.SelectXmlCommand" }
+ }
+
+ It "Returns error for invalid content" {
+ { Select-Xml -Content "hello" -XPath foo | ShouldBeErrorId "InvalidCastToXmlDocument,Microsoft.PowerShell.Commands.SelectXmlCommand" }
+ }
+
+ It "ToString() works correctly on nested node" {
+ $node = Select-Xml -Content "onehello" -XPath "//b"
+ $node.ToString() | Should BeExactly "onehello"
+ }
+
+ It "ToString() works correctly with file" {
+ $testfile = Join-Path "$testdrive" "test.xml"
+ Set-Content -Path $testfile -Value "hello"
+ $node = Select-Xml -Path $testfile -XPath "//b"
+ $node.ToString() | Should BeExactly "hello:$testfile"
}
}
}