From b0a260d97a66b5e3b91594c82682cad7db5134fc Mon Sep 17 00:00:00 2001 From: PaulHigin Date: Mon, 13 Feb 2017 14:16:02 -0800 Subject: [PATCH 1/4] Fix for duplicate types in TypeTable --- .../engine/InitialSessionState.cs | 30 +++++++++++- test/powershell/Common/TestTypeFile.ps1xml | 13 +++++ .../engine/InitialSessionState.Tests.ps1 | 47 ++++++++++++++++++- 3 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 test/powershell/Common/TestTypeFile.ps1xml diff --git a/src/System.Management.Automation/engine/InitialSessionState.cs b/src/System.Management.Automation/engine/InitialSessionState.cs index 798b5ca4d8d..7f9bb43e74a 100644 --- a/src/System.Management.Automation/engine/InitialSessionState.cs +++ b/src/System.Management.Automation/engine/InitialSessionState.cs @@ -1309,7 +1309,7 @@ public void Add(T item) } /// - /// + /// Add items to this collection. /// /// public void Add(IEnumerable items) @@ -1326,6 +1326,27 @@ public void Add(IEnumerable items) } } + /// + /// Special add for TypeTable type entries that removes redundant file entries. + /// + internal void AddTypeTableTypesInfo(IEnumerable items) + { + if (!(items is IEnumerable)) { throw new PSInvalidOperationException(); } + + lock (_syncObject) + { + foreach (var element in items) + { + var typeEntry = element as SessionStateTypeEntry; + if (typeEntry.TypeData != null) + { + // Skip type file entries. + _internalCollection.Add(element); + } + } + } + } + /// /// Get enumerator for this collection. /// @@ -3851,7 +3872,12 @@ internal void UpdateTypes(ExecutionContext context, bool updateOnly) context.TypeTable = typeTable; Types.Clear(); - Types.Add(typeTable.typesInfo); + + // A TypeTable contains types info along with type file references used to create the types info, + // which is redundant information. When resused in a runspace the ISS unpacks the file types again + // resulting in duplicate types and duplication errors when processed. + // So use this special Add method to filter all types files found in the TypeTable. + Types.AddTypeTableTypesInfo(typeTable.typesInfo); return; } diff --git a/test/powershell/Common/TestTypeFile.ps1xml b/test/powershell/Common/TestTypeFile.ps1xml new file mode 100644 index 00000000000..c081303d06a --- /dev/null +++ b/test/powershell/Common/TestTypeFile.ps1xml @@ -0,0 +1,13 @@ + + + + + System.Array + + + Count + Length + + + + diff --git a/test/powershell/engine/InitialSessionState.Tests.ps1 b/test/powershell/engine/InitialSessionState.Tests.ps1 index 85b1bec4fd1..68fd96abf67 100644 --- a/test/powershell/engine/InitialSessionState.Tests.ps1 +++ b/test/powershell/engine/InitialSessionState.Tests.ps1 @@ -54,4 +54,49 @@ Describe "InitialSessionState capacity" -Tags CI { $ps.AddScript('New-Alias -Name a5000 -Value f1; a5000').Invoke() | Should Be "fn f1" $ps.Streams.Error | Should Be $null } -} \ No newline at end of file +} + +## +## A reused InitialSessionState created from a TypeTable should not have duplicate types. +## +Describe "TypeTable duplicate types in reused runspace InitialSessionState" -Tags 'Feature' { + + BeforeAll { + + $typeTable = [System.Management.Automation.Runspaces.TypeTable]::new([string[]](Join-Path $PSScriptRoot "../Common/TestTypeFile.ps1xml")) + [initialsessionstate] $iss = [initialsessionstate]::Create() + $iss.Types.Add($typeTable) + [runspace] $rs1 = [runspacefactory]::CreateRunspace($iss) + + # Process TypeTable types from ISS + $rs1.Open() + + # Get processed ISS from runspace. + $issReused = $rs1.InitialSessionState.Clone() + $issReused.ThrowOnRunspaceOpenError = $true + + # Create new runspace with reused ISS. + $rs2 = [runspacefactory]::CreateRunspace($issReused) + } + + AfterAll { + + if ($rs1 -ne $null) { $rs1.Dispose() } + if ($rs2 -ne $null) { $rs2.Dispose() } + } + + It "Verifies that a reused InitialSessionState object created from a TypeTable object does not have duplicate types" { + + $errs = $null + try + { + $rs2.Open() + } + catch + { + $errs = $_ + } + + $errs | Should Be $null + } +} From 73c6394ee9b2ab117fbb8c6b433f7f057800cc08 Mon Sep 17 00:00:00 2001 From: PaulHigin Date: Wed, 15 Feb 2017 13:13:32 -0800 Subject: [PATCH 2/4] Added new test to verify shared TypeTable is not allowed in ISS types --- test/powershell/Common/TestTypeFile.ps1xml | 2 +- .../engine/InitialSessionState.Tests.ps1 | 93 +++++++++++++------ 2 files changed, 68 insertions(+), 27 deletions(-) diff --git a/test/powershell/Common/TestTypeFile.ps1xml b/test/powershell/Common/TestTypeFile.ps1xml index c081303d06a..6e22c9cf3dc 100644 --- a/test/powershell/Common/TestTypeFile.ps1xml +++ b/test/powershell/Common/TestTypeFile.ps1xml @@ -5,7 +5,7 @@ System.Array - Count + Counts Length diff --git a/test/powershell/engine/InitialSessionState.Tests.ps1 b/test/powershell/engine/InitialSessionState.Tests.ps1 index 68fd96abf67..214f6fbac9d 100644 --- a/test/powershell/engine/InitialSessionState.Tests.ps1 +++ b/test/powershell/engine/InitialSessionState.Tests.ps1 @@ -59,44 +59,85 @@ Describe "InitialSessionState capacity" -Tags CI { ## ## A reused InitialSessionState created from a TypeTable should not have duplicate types. ## -Describe "TypeTable duplicate types in reused runspace InitialSessionState" -Tags 'Feature' { +Describe "TypeTable duplicate types in reused runspace InitialSessionState TypeTable" -Tags 'Feature' { - BeforeAll { + Context "No duplicate types test" { - $typeTable = [System.Management.Automation.Runspaces.TypeTable]::new([string[]](Join-Path $PSScriptRoot "../Common/TestTypeFile.ps1xml")) - [initialsessionstate] $iss = [initialsessionstate]::Create() - $iss.Types.Add($typeTable) - [runspace] $rs1 = [runspacefactory]::CreateRunspace($iss) + BeforeAll { - # Process TypeTable types from ISS - $rs1.Open() + $typeTable = [System.Management.Automation.Runspaces.TypeTable]::new([string[]](Join-Path $PSScriptRoot "../Common/TestTypeFile.ps1xml")) + [initialsessionstate] $iss = [initialsessionstate]::Create() + $iss.Types.Add($typeTable) + [runspace] $rs1 = [runspacefactory]::CreateRunspace($iss) - # Get processed ISS from runspace. - $issReused = $rs1.InitialSessionState.Clone() - $issReused.ThrowOnRunspaceOpenError = $true + # Process TypeTable types from ISS + $rs1.Open() - # Create new runspace with reused ISS. - $rs2 = [runspacefactory]::CreateRunspace($issReused) - } + # Get processed ISS from runspace. + $issReused = $rs1.InitialSessionState.Clone() + $issReused.ThrowOnRunspaceOpenError = $true - AfterAll { + # Create new runspace with reused ISS. + $rs2 = [runspacefactory]::CreateRunspace($issReused) + } + + AfterAll { + + if ($rs1 -ne $null) { $rs1.Dispose() } + if ($rs2 -ne $null) { $rs2.Dispose() } + } + + It "Verifies that a reused InitialSessionState object created from a TypeTable object does not have duplicate types" { - if ($rs1 -ne $null) { $rs1.Dispose() } - if ($rs2 -ne $null) { $rs2.Dispose() } + $errs = $null + try + { + $rs2.Open() + } + catch + { + $errs = $_ + } + + $errs | Should Be $null + } } - It "Verifies that a reused InitialSessionState object created from a TypeTable object does not have duplicate types" { + Context "Cannot use shared TypeTable in ISS test" { - $errs = $null - try - { - $rs2.Open() + BeforeAll { + + # Create default ISS and add shared TypeTable. + $typeTable = [System.Management.Automation.Runspaces.TypeTable]::new([string[]](Join-Path $PSScriptRoot "../Common/TestTypeFile.ps1xml")) + [initialsessionstate] $iss = [initialsessionstate]::CreateDefault2() + $iss.Types.Add($typeTable) + $iss.ThrowOnRunspaceOpenError = $true + [runspace] $rs = [runspacefactory]::CreateRunspace($iss) } - catch - { - $errs = $_ + + AfterAll { + + if ($rs -ne $null) { $rs.Dispose() } } - $errs | Should Be $null + It "Verifies that shared TypeTable is not allowed in ISS" { + + # Process TypeTable types from ISS. + $errorId = "" + try + { + $rs.Open() + throw "No Exception!" + } + catch + { + if ($_.Exception.InnerException -ne $null) + { + $errorId = $_.Exception.InnerException.ErrorRecord.FullyQualifiedErrorId + } + } + + $errorId | Should Be "ErrorsUpdatingTypes" + } } } From de7ad41c25714bbc90ce7068567998767b289063 Mon Sep 17 00:00:00 2001 From: PaulHigin Date: Thu, 16 Feb 2017 08:52:30 -0800 Subject: [PATCH 3/4] Changes per code review --- .../engine/InitialSessionState.cs | 2 +- test/powershell/engine/InitialSessionState.Tests.ps1 | 12 +----------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/System.Management.Automation/engine/InitialSessionState.cs b/src/System.Management.Automation/engine/InitialSessionState.cs index 7f9bb43e74a..3f4e20fb3a2 100644 --- a/src/System.Management.Automation/engine/InitialSessionState.cs +++ b/src/System.Management.Automation/engine/InitialSessionState.cs @@ -1331,7 +1331,7 @@ public void Add(IEnumerable items) /// internal void AddTypeTableTypesInfo(IEnumerable items) { - if (!(items is IEnumerable)) { throw new PSInvalidOperationException(); } + if (typeof(T) != typeof(SessionStateTypeEntry)) { throw new PSInvalidOperationException(); } lock (_syncObject) { diff --git a/test/powershell/engine/InitialSessionState.Tests.ps1 b/test/powershell/engine/InitialSessionState.Tests.ps1 index 214f6fbac9d..3d402c09326 100644 --- a/test/powershell/engine/InitialSessionState.Tests.ps1 +++ b/test/powershell/engine/InitialSessionState.Tests.ps1 @@ -89,17 +89,7 @@ Describe "TypeTable duplicate types in reused runspace InitialSessionState TypeT It "Verifies that a reused InitialSessionState object created from a TypeTable object does not have duplicate types" { - $errs = $null - try - { - $rs2.Open() - } - catch - { - $errs = $_ - } - - $errs | Should Be $null + { $rs2.Open() } | Should Not Throw } } From 1f3292145b08190ef569543dd0c7ccfe6a0b23e5 Mon Sep 17 00:00:00 2001 From: PaulHigin Date: Thu, 16 Feb 2017 09:43:27 -0800 Subject: [PATCH 4/4] CR test fix --- test/powershell/engine/InitialSessionState.Tests.ps1 | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/test/powershell/engine/InitialSessionState.Tests.ps1 b/test/powershell/engine/InitialSessionState.Tests.ps1 index 3d402c09326..547bbddbcfb 100644 --- a/test/powershell/engine/InitialSessionState.Tests.ps1 +++ b/test/powershell/engine/InitialSessionState.Tests.ps1 @@ -121,13 +121,8 @@ Describe "TypeTable duplicate types in reused runspace InitialSessionState TypeT } catch { - if ($_.Exception.InnerException -ne $null) - { - $errorId = $_.Exception.InnerException.ErrorRecord.FullyQualifiedErrorId - } + $_.Exception.InnerException.ErrorRecord.FullyQualifiedErrorId | Should Be "ErrorsUpdatingTypes" } - - $errorId | Should Be "ErrorsUpdatingTypes" } } }