chore(home): mirror from kalinamall (038363c) with papatramp URLs
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
. (Join-Path $PSScriptRoot '_TestLib.ps1')
|
||||
. (Join-Path $PSScriptRoot '_DeployFunctionsLoader.ps1')
|
||||
$repo = Get-RdpMonitorRepoRoot
|
||||
|
||||
Invoke-RdpMonitorTestCase -Name 'Deploy functions load (RDP_DEPLOY_FUNCTIONS_ONLY)' -Script {
|
||||
Assert-CommandExists -Name 'Initialize-RdpMonitorDeployTaskQuery'
|
||||
Assert-CommandExists -Name 'Test-RdpMonitorDeployMainTaskNeedsUnlimitedExecutionTime'
|
||||
Assert-CommandExists -Name 'Write-RdpMonitorDeployScheduledTaskVerification'
|
||||
Assert-CommandExists -Name 'Get-RdpMonitorDeployTaskExecutionTimeLimitLabelFromResolved'
|
||||
Assert-CommandExists -Name 'Convert-RdpMonitorDeployTaskExecutionTimeLimitValue'
|
||||
}
|
||||
|
||||
Invoke-RdpMonitorTestCase -Name 'Deploy ExecutionTimeLimit accepts PT0S string (Get-ScheduledTask shape)' -Script {
|
||||
Assert-True -Condition (Test-RdpMonitorDeployTaskExecutionLimitUnlimitedValue -Limit 'PT0S') `
|
||||
-Message 'PT0S string must be treated as unlimited'
|
||||
$resolved = [pscustomobject]@{ Limit = 'PT0S'; Source = 'Get-ScheduledTask' }
|
||||
$label = Get-RdpMonitorDeployTaskExecutionTimeLimitLabelFromResolved -Resolved $resolved
|
||||
Assert-True -Condition ($label -eq 'PT0S') -Message "Expected PT0S label, got $label"
|
||||
Assert-True -Condition (Test-RdpMonitorDeployTaskExecutionLimitUnlimitedValue -Limit $resolved.Limit) `
|
||||
-Message 'Resolved PT0S string must pass unlimited check'
|
||||
}
|
||||
|
||||
Invoke-RdpMonitorTestCase -Name 'Deploy pre-check task limit (no throw on early path)' -Script {
|
||||
$needsFix = Test-RdpMonitorDeployMainTaskNeedsUnlimitedExecutionTime -ShareRoot $repo -TaskName 'RDP-Login-Monitor-UnitTest-Missing'
|
||||
Assert-True -Condition ($needsFix -is [bool]) -Message 'Test-RdpMonitorDeployMainTaskNeedsUnlimitedExecutionTime must return bool'
|
||||
}
|
||||
|
||||
Invoke-RdpMonitorTestCase -Name 'Deploy verification after Initialize (no missing command)' -Script {
|
||||
[void](Initialize-RdpMonitorDeployTaskQuery -ShareRoot $repo)
|
||||
Assert-CommandExists -Name 'Get-RdpMonitorScheduledTaskExecutionTimeLimitResolved'
|
||||
$ok = Write-RdpMonitorDeployScheduledTaskVerification -ShareRoot $repo -TaskName 'RDP-Login-Monitor-UnitTest-Missing'
|
||||
Assert-True -Condition ($ok -is [bool]) -Message 'Write-RdpMonitorDeployScheduledTaskVerification must return bool'
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
. (Join-Path $PSScriptRoot '_TestLib.ps1')
|
||||
|
||||
$repo = Get-RdpMonitorRepoRoot
|
||||
$files = @(
|
||||
'Deploy-LoginMonitor.ps1',
|
||||
'Login_Monitor.ps1',
|
||||
'Sac-Client.ps1',
|
||||
'RdpMonitor-TaskQuery.ps1',
|
||||
'update-rdp-monitor.ps1'
|
||||
)
|
||||
|
||||
foreach ($rel in $files) {
|
||||
$path = Join-Path $repo $rel
|
||||
Invoke-RdpMonitorTestCase -Name "Syntax: $rel" -Script {
|
||||
Assert-True -Condition (Test-Path -LiteralPath $path) -Message "Missing $path"
|
||||
$errs = $null
|
||||
[void][System.Management.Automation.Language.Parser]::ParseFile($path, [ref]$null, [ref]$errs)
|
||||
if ($errs -and $errs.Count -gt 0) {
|
||||
throw ($errs | ForEach-Object { $_.ToString() } | Out-String)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
. (Join-Path $PSScriptRoot '_TestLib.ps1')
|
||||
|
||||
function Test-RdpSecurityPollCursorResolve {
|
||||
param(
|
||||
[datetime]$Now,
|
||||
[int]$MaxAgeMinutes,
|
||||
[Nullable[datetime]]$SavedCursor
|
||||
)
|
||||
|
||||
$maxAgeMin = [math]::Max(1, $MaxAgeMinutes)
|
||||
$lookbackFloor = $Now.AddMinutes(-1 * $maxAgeMin)
|
||||
if ($null -eq $SavedCursor) {
|
||||
return $lookbackFloor
|
||||
}
|
||||
if ($SavedCursor -lt $lookbackFloor) {
|
||||
return $lookbackFloor
|
||||
}
|
||||
return $SavedCursor
|
||||
}
|
||||
|
||||
Invoke-RdpMonitorTestCase -Name 'Security cursor: missing file uses lookback floor' -Script {
|
||||
$now = Get-Date '2026-06-15T12:00:00'
|
||||
$resolved = Test-RdpSecurityPollCursorResolve -Now $now -MaxAgeMinutes 60 -SavedCursor $null
|
||||
$expected = $now.AddMinutes(-60)
|
||||
Assert-True -Condition ($resolved -eq $expected) -Message 'Expected lookback floor when cursor missing'
|
||||
}
|
||||
|
||||
Invoke-RdpMonitorTestCase -Name 'Security cursor: stale saved cursor capped to lookback floor' -Script {
|
||||
$now = Get-Date '2026-06-15T12:00:00'
|
||||
$stale = $now.AddMinutes(-120)
|
||||
$resolved = Test-RdpSecurityPollCursorResolve -Now $now -MaxAgeMinutes 60 -SavedCursor $stale
|
||||
$expected = $now.AddMinutes(-60)
|
||||
Assert-True -Condition ($resolved -eq $expected) -Message 'Expected cap at lookback floor for stale cursor'
|
||||
}
|
||||
|
||||
Invoke-RdpMonitorTestCase -Name 'Security cursor: recent saved cursor preserved' -Script {
|
||||
$now = Get-Date '2026-06-15T12:00:00'
|
||||
$recent = $now.AddMinutes(-5)
|
||||
$resolved = Test-RdpSecurityPollCursorResolve -Now $now -MaxAgeMinutes 60 -SavedCursor $recent
|
||||
Assert-True -Condition ($resolved -eq $recent) -Message 'Expected recent cursor unchanged'
|
||||
}
|
||||
|
||||
Invoke-RdpMonitorTestCase -Name 'Login_Monitor defines Security poll cursor helpers' -Script {
|
||||
$repo = Get-RdpMonitorRepoRoot
|
||||
$text = Get-Content -LiteralPath (Join-Path $repo 'Login_Monitor.ps1') -Raw
|
||||
Assert-True -Condition ($text -match 'Get-RdpSecurityPollCursor') -Message 'Missing Get-RdpSecurityPollCursor'
|
||||
Assert-True -Condition ($text -match 'Set-RdpSecurityPollCursor') -Message 'Missing Set-RdpSecurityPollCursor'
|
||||
Assert-True -Condition ($text -match '\$SecurityPollCursorFile') -Message 'Missing SecurityPollCursorFile'
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
. (Join-Path $PSScriptRoot '_TestLib.ps1')
|
||||
|
||||
function Test-RdpMonitorDeploySacHostLabelStrictMode {
|
||||
Set-StrictMode -Version Latest
|
||||
$hostLabel = [string]$env:COMPUTERNAME
|
||||
if (Get-Variable -Name ServerDisplayName -Scope Script -ErrorAction SilentlyContinue) {
|
||||
$sdn = (Get-Variable -Name ServerDisplayName -Scope Script -ValueOnly)
|
||||
if ($null -ne $sdn -and -not [string]::IsNullOrWhiteSpace([string]$sdn)) {
|
||||
$hostLabel = [string]$sdn.Trim()
|
||||
}
|
||||
}
|
||||
return $hostLabel
|
||||
}
|
||||
|
||||
Invoke-RdpMonitorTestCase -Name 'Deploy SAC host label without ServerDisplayName (StrictMode)' -Script {
|
||||
$label = Test-RdpMonitorDeploySacHostLabelStrictMode
|
||||
Assert-True -Condition (-not [string]::IsNullOrWhiteSpace($label)) -Message 'Host label must not be empty'
|
||||
Assert-True -Condition ($label -eq [string]$env:COMPUTERNAME) -Message 'Expected COMPUTERNAME when ServerDisplayName unset'
|
||||
}
|
||||
|
||||
Invoke-RdpMonitorTestCase -Name 'Deploy SAC host label with ServerDisplayName (StrictMode)' -Script {
|
||||
$script:ServerDisplayName = 'Test-Server-Display'
|
||||
try {
|
||||
$label = Test-RdpMonitorDeploySacHostLabelStrictMode
|
||||
Assert-True -Condition ($label -eq 'Test-Server-Display') -Message 'Expected ServerDisplayName value'
|
||||
} finally {
|
||||
Remove-Variable -Name ServerDisplayName -Scope Script -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
Invoke-RdpMonitorTestCase -Name 'Login_Monitor -SendDeploySacNotice does not fail on StrictMode host label' -Script {
|
||||
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
|
||||
$principal = New-Object Security.Principal.WindowsPrincipal($identity)
|
||||
if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
|
||||
Write-Host 'SKIP: requires elevated PowerShell (administrator)'
|
||||
return
|
||||
}
|
||||
|
||||
$repo = Get-RdpMonitorRepoRoot
|
||||
$tempRoot = Join-Path $env:TEMP ("rdp-monitor-test-{0}" -f [guid]::NewGuid().ToString('N'))
|
||||
New-Item -ItemType Directory -Path $tempRoot -Force | Out-Null
|
||||
New-Item -ItemType Directory -Path (Join-Path $tempRoot 'Logs') -Force | Out-Null
|
||||
|
||||
$settings = @'
|
||||
$UseSAC = 'off'
|
||||
'@
|
||||
$settingsPath = Join-Path $tempRoot 'login_monitor.settings.ps1'
|
||||
[System.IO.File]::WriteAllText($settingsPath, $settings, (New-Object System.Text.UTF8Encoding $true))
|
||||
|
||||
Copy-Item -LiteralPath (Join-Path $repo 'Login_Monitor.ps1') -Destination (Join-Path $tempRoot 'Login_Monitor.ps1') -Force
|
||||
Copy-Item -LiteralPath (Join-Path $repo 'Sac-Client.ps1') -Destination (Join-Path $tempRoot 'Sac-Client.ps1') -Force
|
||||
|
||||
$psi = New-Object System.Diagnostics.ProcessStartInfo
|
||||
$psi.FileName = "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe"
|
||||
$psi.Arguments = '-NoProfile -ExecutionPolicy Bypass -File "{0}" -SendDeploySacNotice' -f (Join-Path $tempRoot 'Login_Monitor.ps1')
|
||||
$psi.WorkingDirectory = $tempRoot
|
||||
$psi.RedirectStandardOutput = $true
|
||||
$psi.RedirectStandardError = $true
|
||||
$psi.UseShellExecute = $false
|
||||
$psi.CreateNoWindow = $true
|
||||
|
||||
$proc = [System.Diagnostics.Process]::Start($psi)
|
||||
$stdout = $proc.StandardOutput.ReadToEnd()
|
||||
$stderr = $proc.StandardError.ReadToEnd()
|
||||
$proc.WaitForExit()
|
||||
|
||||
try {
|
||||
if ($stderr -match 'ServerDisplayName|VariableIsUndefined') {
|
||||
throw "SendDeploySacNotice stderr contains StrictMode error: $stderr"
|
||||
}
|
||||
Assert-True -Condition ($proc.ExitCode -eq 0) -Message "Expected exit 0 with UseSAC=off, got $($proc.ExitCode); stderr=$stderr stdout=$stdout"
|
||||
} finally {
|
||||
Remove-Item -LiteralPath $tempRoot -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
. (Join-Path $PSScriptRoot '_TestLib.ps1')
|
||||
|
||||
$repo = Get-RdpMonitorRepoRoot
|
||||
$taskQuery = Join-Path $repo 'RdpMonitor-TaskQuery.ps1'
|
||||
|
||||
Invoke-RdpMonitorTestCase -Name 'TaskQuery file exists' -Script {
|
||||
Assert-True -Condition (Test-Path -LiteralPath $taskQuery) -Message "Missing $taskQuery"
|
||||
}
|
||||
|
||||
Invoke-RdpMonitorTestCase -Name 'TaskQuery dot-source defines core commands' -Script {
|
||||
. $taskQuery
|
||||
Assert-CommandExists -Name 'Get-RdpMonitorScheduledTaskExecutionTimeLimitResolved'
|
||||
Assert-CommandExists -Name 'Test-RdpMonitorScheduledTaskNeedsUnlimitedExecutionTimeLimit'
|
||||
Assert-CommandExists -Name 'Get-RdpMonitorScheduledTaskExecutionTimeLimitLabel'
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
# Dot-source from a test .ps1 at script scope after _TestLib.ps1 (not from a function/scriptblock).
|
||||
if ($script:RdpMonitorDeployFunctionsLoaded) { return }
|
||||
|
||||
$repo = Get-RdpMonitorRepoRoot
|
||||
$prev = $env:RDP_DEPLOY_FUNCTIONS_ONLY
|
||||
$env:RDP_DEPLOY_FUNCTIONS_ONLY = '1'
|
||||
try {
|
||||
. (Join-Path $repo 'Deploy-LoginMonitor.ps1')
|
||||
} finally {
|
||||
if ($null -eq $prev) {
|
||||
Remove-Item Env:RDP_DEPLOY_FUNCTIONS_ONLY -ErrorAction SilentlyContinue
|
||||
} else {
|
||||
$env:RDP_DEPLOY_FUNCTIONS_ONLY = $prev
|
||||
}
|
||||
}
|
||||
$script:RdpMonitorDeployFunctionsLoaded = $true
|
||||
@@ -0,0 +1,39 @@
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$script:RdpMonitorDeployFunctionsLoaded = $false
|
||||
|
||||
function Get-RdpMonitorRepoRoot { return (Resolve-Path (Join-Path $PSScriptRoot '..\..')).Path
|
||||
}
|
||||
|
||||
function Assert-True {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)][bool]$Condition,
|
||||
[Parameter(Mandatory = $true)][string]$Message
|
||||
)
|
||||
if (-not $Condition) {
|
||||
throw "FAIL: $Message"
|
||||
}
|
||||
}
|
||||
|
||||
function Assert-CommandExists {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)][string]$Name
|
||||
)
|
||||
$cmd = Get-Command -Name $Name -ErrorAction SilentlyContinue
|
||||
Assert-True -Condition ($null -ne $cmd) -Message "Command not found: $Name"
|
||||
}
|
||||
|
||||
function Invoke-RdpMonitorTestCase {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)][string]$Name,
|
||||
[Parameter(Mandatory = $true)][scriptblock]$Script
|
||||
)
|
||||
try {
|
||||
& $Script
|
||||
Write-Host "PASS: $Name"
|
||||
} catch {
|
||||
Write-Host "FAIL: $Name - $($_.Exception.Message)"
|
||||
throw
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user