Tests/Authentication.Tests.ps1
|
using namespace System.Collections.Generic BeforeAll { $TMModuleDirectory = (Get-ChildItem $PSScriptRoot | Select-Object -First 1).Directory.Parent Import-Module "$TMModuleDirectory\TransitionManager.psm1" -Force . $TMModuleDirectory\Classes\TransitionManager.Classes.ps1 $ValidSessions = [List[TMSession]]::new() $Global:TMSessions = @{} $SessionsWithVersions = @{ tmad61 = '6.1.2.3' tmad62 = '6.2.3.4' other61 = '6.1.6.9' some60 = '6.0.0.1' ya61 = '6.1.6.6' } foreach ($ServerName in $SessionsWithVersions.Keys) { $Session = [TMSession]::new($ServerName, "$ServerName.transitionmanager.net", $true) $Session.TMVersion = $SessionsWithVersions.$ServerName $ValidSessions.Add($Session) } $ValidSessions.Item(0).Name = 'Default' foreach ($Session in $ValidSessions) { $Global:TMSessions.Add($Session.Name, $Session) } $NonExistingName = 'this-is-a-name-that-does-not-exist' $SingleVersion = '6.1.2.3' $MultipleVersions = '6.1*' $MajorVersion = '6*' $NonExistingVersion = '4.0.6.8' $SingleServerMatch = $ValidSessions.Item(0).TMServer $Multiple61ServerMatch = '*61' $MultipleTMADServerMatch = 'tmad*' } AfterAll { foreach ($Session in $ValidSessions) { $Session.Dispose() } } Describe 'Get-TMSession byObject' { It 'Returns the provided valid TMSession' { foreach ($ValidSession in $ValidSessions) { $Session = Get-TMSession -TMSession $ValidSession $Session.GetType().Name | Should -EQ 'TMSession' } } It 'Throws on invalid TMSession' { $InvalidSession = [TMSession]::new('my session name', 'my server', $true <# AllowInsecureSSL #>) try { { Get-TMSession -TMSession $InvalidSession } | Should -Throw } finally { $InvalidSession.Dispose() } } } Describe 'Get-TMSession by Name' { It 'Returns the valid, specified session' { foreach ($ValidSession in $ValidSessions) { $Session = Get-TMSession -Name $ValidSession.Name $Session.GetType().Name | Should -EQ 'TMSession' $Session.Count | Should -EQ 1 } } It 'Returns all sessiones specified by name' { $Sessions = Get-TMSession -Name $ValidSessions.Name $Sessions.Count | Should -EQ $ValidSessions.Count foreach ($Session in $Sessions) { $Session.GetType().Name | Should -EQ 'TMSession' } } It 'Throws if the one specified session is not found' { { Get-TMSession -Name $NonExistingName } | Should -Throw } } Describe 'Get-TMSession by Version' { It 'Returns one valid session speicified by Version' { $Session = Get-TMSession -Version $SingleVersion $Session.GetType().Name | Should -EQ 'TMSession' $Session.Count | Should -EQ 1 } It 'Returns all sessions matching major and minor' { $Sessions = Get-TMSession -Version $MultipleVersions $Sessions.GetType().Name | Should -EQ 'TMSession[]' } It 'Returns all sessions matching major' { $Sessions = Get-TMSession -Version $MajorVersion $Sessions.Count | Should -EQ $ValidSessions.Count } It 'Throws if the one specified session is not found' { { Get-TMSession -Version $NonExistingVersion } | Should -Throw } } Describe 'Get-TMSession by Server' { It 'Returns a single session by matching server' { $Session = Get-TMSession -Server $SingleServerMatch $Session.GetType().Name | Should -EQ 'TMSession' $Session.Count | Should -EQ $ValidSessions.Where({$_.TMServer -eq $SingleServerMatch}).Count } It 'Returns all sessions matching the server name ending in 61' { $Sessions = Get-TMSession -Server $Multiple61ServerMatch $Sessions.GetType().Name | Should -EQ 'TMSession[]' $Sessions.Count | Should -EQ $ValidSessions.Where({$_.TMServer -like "$Multiple61ServerMatch*"}).Count } It 'Returns all sessions matching the server name starting with "tmad"' { $Sessions = Get-TMSession -Server $MultipleTMADServerMatch $Sessions.GetType().Name | Should -EQ 'TMSession[]' $Sessions.Count | Should -EQ $ValidSessions.Where({$_.TMServer -like "$MultipleTMADServerMatch*"}).Count } It 'Throws if the specified server is invalid' { { Get-TMSession -Server $NonExistingName } | Should -Throw } } Describe 'TMSession token refresh resource disposal' { It 'implements IDisposable and removes its subscriber and event job' { $SessionName = 'dispose-' + [Guid]::NewGuid().ToString() $EventName = $SessionName + '_TMSession.TokenRefreshTimer.Elapsed_*' $Session = [TMSession]::new($SessionName) $Timer = $Session.Authentication.OAuth.tokenRefreshTimer try { $Session -is [System.IDisposable] | Should -BeTrue @(Get-EventSubscriber -SourceIdentifier $EventName -ErrorAction Ignore).Count | Should -Be 1 $EventJob = @(Get-Job -Name $EventName -ErrorAction Ignore) $EventJob.Count | Should -Be 1 [Object]::ReferenceEquals($Session.tokenRefreshEventJob, $EventJob[0]) | Should -BeTrue $Timer.Enabled | Should -BeTrue $Session.Dispose() @(Get-EventSubscriber -SourceIdentifier $EventName -ErrorAction Ignore).Count | Should -Be 0 @(Get-Job -Name $EventName -ErrorAction Ignore).Count | Should -Be 0 { $Timer.Start() } | Should -Throw $Session.Authentication.OAuth.tokenRefreshTimer | Should -BeNullOrEmpty $Session.tokenRefreshEventJob | Should -BeNullOrEmpty $Session.tokenRefreshEventSourceIdentifier | Should -BeNullOrEmpty } finally { $Session.Dispose() } } It 'can be disposed repeatedly' { $SessionName = 'dispose-twice-' + [Guid]::NewGuid().ToString() $EventName = $SessionName + '_TMSession.TokenRefreshTimer.Elapsed_*' $Session = [TMSession]::new($SessionName) { $Session.Dispose(); $Session.Dispose() } | Should -Not -Throw @(Get-EventSubscriber -SourceIdentifier $EventName -ErrorAction Ignore).Count | Should -Be 0 @(Get-Job -Name $EventName -ErrorAction Ignore).Count | Should -Be 0 } It 'does not remove resources owned by another same-named session' { $SessionName = 'same-name-' + [Guid]::NewGuid().ToString() $EventName = $SessionName + '_TMSession.TokenRefreshTimer.Elapsed_*' $FirstSession = [TMSession]::new($SessionName) $SecondSession = [TMSession]::new($SessionName) try { @(Get-EventSubscriber -SourceIdentifier $EventName -ErrorAction Ignore).Count | Should -Be 2 @(Get-Job -Name $EventName -ErrorAction Ignore).Count | Should -Be 2 $FirstSession.Dispose() @(Get-EventSubscriber -SourceIdentifier $EventName -ErrorAction Ignore).Count | Should -Be 1 @(Get-Job -Name $EventName -ErrorAction Ignore).Count | Should -Be 1 } finally { $FirstSession.Dispose() $SecondSession.Dispose() } } It 'removes its event job when its subscriber was already unregistered' { $SessionName = 'unregistered-' + [Guid]::NewGuid().ToString() $EventName = $SessionName + '_TMSession.TokenRefreshTimer.Elapsed_*' $Session = [TMSession]::new($SessionName) try { Get-EventSubscriber -SourceIdentifier $EventName | Unregister-Event -Force @(Get-Job -Name $EventName -ErrorAction Ignore).Count | Should -Be 1 $Session.Dispose() @(Get-Job -Name $EventName -ErrorAction Ignore).Count | Should -Be 0 } finally { $Session.Dispose() } } It 'releases refresh resources after an expired-token refresh failure' { $SessionName = 'refresh-failure-' + [Guid]::NewGuid().ToString() $EventName = $SessionName + '_TMSession.TokenRefreshTimer.Elapsed_*' $Session = [TMSession]::new($SessionName) try { $Session.Authentication.OAuth.ExpirationSeconds = 1 $Session.Authentication.OAuth.GrantedDate = (Get-Date).AddMinutes(-1) $Session.RefreshAccessToken() @(Get-EventSubscriber -SourceIdentifier $EventName -ErrorAction Ignore).Count | Should -Be 0 @(Get-Job -Name $EventName -ErrorAction Ignore).Count | Should -Be 0 $Session.Authentication.OAuth.tokenRefreshTimer | Should -BeNullOrEmpty } finally { $Session.Dispose() } } } Describe 'Remove-TMSession resource disposal' { It 'disposes a successfully removed session' { $SessionName = 'remove-success-' + [Guid]::NewGuid().ToString() $EventName = $SessionName + '_TMSession.TokenRefreshTimer.Elapsed_*' $Session = [TMSession]::new($SessionName, 'remove-success.transitionmanager.net', $true) $Global:TMSessions[$SessionName] = $Session Mock Invoke-WebRequest -ModuleName TransitionManager { [PSCustomObject]@{ StatusCode = 200 Content = '{"status":"success"}' } } try { $Session | Remove-TMSession $Global:TMSessions.ContainsKey($SessionName) | Should -BeFalse @(Get-EventSubscriber -SourceIdentifier $EventName -ErrorAction Ignore).Count | Should -Be 0 @(Get-Job -Name $EventName -ErrorAction Ignore).Count | Should -Be 0 $Session.Authentication.OAuth.tokenRefreshTimer | Should -BeNullOrEmpty } finally { $Session.Dispose() $Global:TMSessions.Remove($SessionName) } } It 'preserves a session and its resources when sign-out fails' { $SessionName = 'remove-failure-' + [Guid]::NewGuid().ToString() $EventName = $SessionName + '_TMSession.TokenRefreshTimer.Elapsed_*' $Session = [TMSession]::new($SessionName, 'remove-failure.transitionmanager.net', $true) $Global:TMSessions[$SessionName] = $Session Mock Invoke-WebRequest -ModuleName TransitionManager { throw 'Expected sign-out failure' } try { $Session | Remove-TMSession -ErrorAction SilentlyContinue $Global:TMSessions.ContainsKey($SessionName) | Should -BeTrue @(Get-EventSubscriber -SourceIdentifier $EventName -ErrorAction Ignore).Count | Should -Be 1 @(Get-Job -Name $EventName -ErrorAction Ignore).Count | Should -Be 1 $Session.Authentication.OAuth.tokenRefreshTimer.Enabled | Should -BeTrue } finally { $Session.Dispose() $Global:TMSessions.Remove($SessionName) } } } |