private/core-device/Initialize-OSDCoreDevice.Tests.ps1
|
BeforeAll { $tokens = $null $parseErrors = $null $initializerAst = [System.Management.Automation.Language.Parser]::ParseFile( "$PSScriptRoot\Initialize-OSDCoreDevice.ps1", [ref]$tokens, [ref]$parseErrors ) if ($parseErrors.Count -gt 0) { throw ($parseErrors -join "`n") } $snapshotAssignment = $initializerAst.Find({ param($node) $node -is [System.Management.Automation.Language.AssignmentStatementAst] -and $node.Left.Extent.Text -eq '$global:OSDCoreDevice' -and $node.Right.Extent.Text -like '[[]ordered]*' }, $true) $snapshotMap = $snapshotAssignment.Find({ param($node) $node -is [System.Management.Automation.Language.HashtableAst] }, $true) # Evaluate only the actual snapshot mappings, not the initializer's hardware # queries, clock synchronization, disk discovery, or diagnostic writes. $inventoryKeys = @('DiskDrives', 'NetworkAdapters', 'Processors', 'PhysicalMemory', 'NativeOSArchitecture', 'TotalPhysicalMemory') $inventoryMappings = @($snapshotMap.KeyValuePairs | Where-Object { $_.Item1.Value -in $inventoryKeys }) $mappingScript = [scriptblock]::Create( "[ordered]@{`n" + (($inventoryMappings | ForEach-Object { $_.Item1.Extent.Text + ' = ' + $_.Item2.Extent.Text }) -join "`n") + "`n}" ) $initializerFunction = $initializerAst.Find({ param($node) $node -is [System.Management.Automation.Language.FunctionDefinitionAst] }, $true) $statements = $initializerFunction.Body.EndBlock.Statements for ($i = 0; $i -lt $statements.Count; $i++) { if ($statements[$i] -is [System.Management.Automation.Language.AssignmentStatementAst] -and $statements[$i].Left.Extent.Text -eq '$classWin32PhysicalMemory') { $physicalMemoryCollection = [scriptblock]::Create( ($statements[$i..($i + 2)] | ForEach-Object { $_.Extent.Text }) -join "`n" ) break } } } Describe 'Initialize-OSDCoreDevice physical memory collection' { BeforeEach { $LogsPath = $TestDrive Mock Out-File {} } It 'queries modules once and exports the complete diagnostic inventory' { Mock Get-CimInstance { [pscustomobject]@{ DeviceLocator = 'DIMM1'; Speed = 5600; ConfiguredClockSpeed = 4800 } [pscustomobject]@{ DeviceLocator = 'DIMM2'; Speed = 5600; ConfiguredClockSpeed = 4800 } } . $physicalMemoryCollection $classWin32PhysicalMemory.Count | Should -Be 2 $classWin32PhysicalMemory[0].DeviceLocator | Should -Be 'DIMM1' Should -Invoke Get-CimInstance -Times 1 -Exactly -ParameterFilter { $ClassName -eq 'Win32_PhysicalMemory' -and $ErrorAction -eq 'Stop' } Should -Invoke Out-File -Times 2 -Exactly -ParameterFilter { $FilePath -eq (Join-Path $LogsPath 'Win32_PhysicalMemory.txt') } } It 'warns and leaves an empty inventory if module collection fails' { Mock Get-CimInstance { throw 'Memory provider unavailable.' } Mock Write-Warning {} . $physicalMemoryCollection $classWin32PhysicalMemory.Count | Should -Be 0 Should -Invoke Write-Warning -Times 1 -Exactly -ParameterFilter { $Message -like '*Unable to query Win32_PhysicalMemory:*Memory provider unavailable*' } } } Describe 'Initialize-OSDCoreDevice display inventory mappings' { BeforeEach { $classWin32NetworkAdapterConfiguration = @() $classWin32PhysicalMemory = @() } It 'matches IPv4 addresses by adapter index and excludes IPv6 and unassigned addresses' { $classWin32NetworkAdapter = @( [pscustomobject]@{ Name = 'Ethernet'; Index = 1 } [pscustomobject]@{ Name = 'Wi-Fi'; Index = 2 } [pscustomobject]@{ Name = 'Disconnected'; Index = 3 } [pscustomobject]@{ Name = 'IPv6 only'; Index = 4 } ) $classWin32NetworkAdapterConfiguration = @( [pscustomobject]@{ Index = 2; IPAddress = @('192.168.1.20') } [pscustomobject]@{ Index = 1; IPAddress = @('fe80::1', '10.0.0.10', '10.0.0.11') } [pscustomobject]@{ Index = 4; IPAddress = @('fe80::4') } ) $snapshot = & $mappingScript $snapshot.NetworkAdapters[0].IPv4Addresses | Should -Be @('10.0.0.10', '10.0.0.11') $snapshot.NetworkAdapters[1].IPv4Addresses | Should -Be @('192.168.1.20') $snapshot.NetworkAdapters[2].IPv4Addresses.Count | Should -Be 0 $snapshot.NetworkAdapters[3].IPv4Addresses.Count | Should -Be 0 $jsonSnapshot = $snapshot | ConvertTo-Json -Depth 10 -WarningVariable serializationWarnings | ConvertFrom-Json @($serializationWarnings).Count | Should -Be 0 $jsonSnapshot.NetworkAdapters[0].IPv4Addresses | Should -Be @('10.0.0.10', '10.0.0.11') } It 'exposes all six fields from the existing collection variables' { $inventoryMappings.Count | Should -Be 6 $classWin32DiskDrive = [pscustomobject]@{ Model = 'Disk'; ExtraDiskField = 'retained' } $classWin32NetworkAdapter = [pscustomobject]@{ Name = 'Ethernet'; ExtraNetworkField = 'retained' } $classWin32Processor = [pscustomobject]@{ Name = 'CPU'; ExtraProcessorField = 'retained' } $classWin32PhysicalMemory = [pscustomobject]@{ ConfiguredClockSpeed = 4800; Speed = 5600; Capacity = 8GB } $classWin32OperatingSystem = [pscustomobject]@{ OSArchitecture = '64-bit' } $classWin32ComputerSystem = [pscustomobject]@{ TotalPhysicalMemory = 6.5GB } $OSArchitecture = 'override' $snapshot = & $mappingScript $snapshot.NativeOSArchitecture | Should -Be '64-bit' $snapshot.TotalPhysicalMemory | Should -Be 6.5GB $snapshot.DiskDrives[0].Model | Should -Be 'Disk' $snapshot.NetworkAdapters[0].Name | Should -Be 'Ethernet' $snapshot.Processors[0].Name | Should -Be 'CPU' $jsonSnapshot = $snapshot | ConvertTo-Json -Depth 10 | ConvertFrom-Json $xmlPath = Join-Path $TestDrive 'inventory.xml' $snapshot | Export-Clixml -Path $xmlPath $xmlSnapshot = Import-Clixml -Path $xmlPath foreach ($roundTrip in @($jsonSnapshot, $xmlSnapshot)) { $roundTrip.DiskDrives[0].ExtraDiskField | Should -Be 'retained' $roundTrip.NetworkAdapters[0].ExtraNetworkField | Should -Be 'retained' $roundTrip.Processors[0].ExtraProcessorField | Should -Be 'retained' $roundTrip.PhysicalMemory[0].ConfiguredClockSpeed | Should -Be 4800 $roundTrip.PhysicalMemory[0].Speed | Should -Be 5600 $roundTrip.PhysicalMemory[0].Capacity | Should -Be 8GB $roundTrip.TotalPhysicalMemory | Should -Be 6.5GB $roundTrip.NativeOSArchitecture | Should -Be '64-bit' } } It 'excludes deep CIM metadata without truncating JSON or losing hardware properties' { $metadata = [pscustomobject]@{ ClassName = 'TestClass' } $metadata | Add-Member -NotePropertyName Parent -NotePropertyValue $metadata $classWin32DiskDrive = [pscustomobject]@{ Model = 'Disk' DeviceID = 'disk0' Size = [uint64]1TB Capabilities = [uint16[]]@(3, 4) CimClass = $metadata CimInstanceProperties = $metadata CimSystemProperties = $metadata } $classWin32NetworkAdapter = $classWin32DiskDrive $classWin32Processor = $classWin32DiskDrive $classWin32PhysicalMemory = $classWin32DiskDrive $classWin32OperatingSystem = $null $classWin32ComputerSystem = $null $snapshot = & $mappingScript $json = $snapshot | ConvertTo-Json -Depth 10 -WarningVariable serializationWarnings @($serializationWarnings).Count | Should -Be 0 $roundTrip = $json | ConvertFrom-Json foreach ($key in @('DiskDrives', 'NetworkAdapters', 'Processors', 'PhysicalMemory')) { $snapshot[$key][0].PSObject.Properties.Name | Should -Not -Contain 'CimClass' $snapshot[$key][0].PSObject.Properties.Name | Should -Not -Contain 'CimInstanceProperties' $snapshot[$key][0].PSObject.Properties.Name | Should -Not -Contain 'CimSystemProperties' $roundTrip.$key[0].Model | Should -Be 'Disk' $roundTrip.$key[0].Size | Should -Be 1TB $roundTrip.$key[0].Capabilities | Should -Be @(3, 4) } $classWin32DiskDrive.CimClass | Should -Not -BeNullOrEmpty } It 'normalizes <Count> collected objects to arrays without null placeholders' -ForEach @( @{ Count = 0 } @{ Count = 1 } @{ Count = 2 } ) { $objects = @( [pscustomobject]@{ Name = 'One' } [pscustomobject]@{ Name = 'Two' } ) $classWin32DiskDrive = $objects | Select-Object -First $Count $classWin32NetworkAdapter = $objects | Select-Object -First $Count $classWin32Processor = $objects | Select-Object -First $Count $classWin32PhysicalMemory = $objects | Select-Object -First $Count $classWin32OperatingSystem = $null $classWin32ComputerSystem = $null $snapshot = & $mappingScript foreach ($key in @('DiskDrives', 'NetworkAdapters', 'Processors', 'PhysicalMemory')) { ($snapshot[$key] -is [array]) | Should -BeTrue $snapshot[$key].Count | Should -Be $Count } $snapshot.TotalPhysicalMemory | Should -BeNullOrEmpty $snapshot.NativeOSArchitecture | Should -BeNullOrEmpty } } |