Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 35 additions & 11 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -304,11 +304,16 @@ jobs:

coverage-report:
if: github.event_name == 'pull_request'
# Use Linux coverage only: merging all platforms inflates total line count
# because each platform has platform-specific source files (Windows adds ~4500
# lines from registry/service/DISM resources). Single-platform coverage matches
# local `build.ps1 -codecoverage` results and avoids misleadingly low percentages.
needs: [linux-build, linux-pester]
# Use all platforms for changed-code coverage so platform-specific files are
# included. Keep full-codebase coverage Linux-only to avoid inflating its
# denominator with platform-specific sources.
needs:
- linux-build
- linux-pester
- macos-build
- macos-pester
- windows-build
- windows-pester
runs-on: ubuntu-latest
permissions:
pull-requests: write
Expand All @@ -321,7 +326,7 @@ jobs:
- name: Download coverage artifacts
uses: actions/download-artifact@v4
with:
pattern: 'linux*coverage'
pattern: '*coverage'
path: coverage-data

- name: Consolidate coverage data
Expand All @@ -339,30 +344,49 @@ jobs:
$baseSha = $mergeBase
}

# Find all available lcov.info files from coverage artifacts
# Changed-code coverage uses every platform so platform-specific Rust
# files are analyzed. Full-codebase coverage remains Linux-only to
# avoid inflating its denominator with platform-specific sources.
$lcovFiles = Get-ChildItem -Path 'coverage-data' -Filter 'lcov.info' -Recurse
$pesterLcovFiles = Get-ChildItem -Path 'coverage-data' -Filter 'pester-lcov.info' -Recurse
$allLcovFiles = @($lcovFiles) + @($pesterLcovFiles) | Where-Object { $_ }
$linuxLcovFiles = @($allLcovFiles | Where-Object {
($_.FullName -match '[/\\]linux-[^/\\]+-coverage[/\\]') -or
($_.FullName -match '[/\\]linux-coverage[/\\]')
})

if ($allLcovFiles.Count -eq 0) {
Write-Warning 'No coverage data found from any platform.'
"coverage_failed=true" | Out-File -Append -Encoding utf8 -FilePath $env:GITHUB_OUTPUT
return
}
if ($linuxLcovFiles.Count -eq 0) {
Write-Warning 'No Linux coverage data found for the full-codebase report.'
"coverage_failed=true" | Out-File -Append -Encoding utf8 -FilePath $env:GITHUB_OUTPUT
return
}
"coverage_failed=false" | Out-File -Append -Encoding utf8 -FilePath $env:GITHUB_OUTPUT

Write-Verbose -Verbose "Found $($allLcovFiles.Count) LCOV file(s) to merge"
Write-Verbose -Verbose "Found $($allLcovFiles.Count) cross-platform LCOV file(s)"
Write-Verbose -Verbose "Found $($linuxLcovFiles.Count) Linux LCOV file(s)"

# Merge all LCOV files into a single consolidated report
# Merge all platforms for changed-code coverage.
$mergedLcovPath = Join-Path $PWD 'merged-lcov.info'
if ($allLcovFiles.Count -eq 1) {
Copy-Item -Path $allLcovFiles[0].FullName -Destination $mergedLcovPath
} else {
Merge-LcovFile -Path ($allLcovFiles | ForEach-Object { $_.FullName }) -OutputPath $mergedLcovPath -Verbose
}

# Full codebase coverage report (always computed)
$fullReport = Get-FullCodeCoverageReport -LcovPath $mergedLcovPath -Verbose
# Merge Linux coverage separately for the full-codebase report.
$linuxMergedLcovPath = Join-Path $PWD 'linux-merged-lcov.info'
if ($linuxLcovFiles.Count -eq 1) {
Copy-Item -Path $linuxLcovFiles[0].FullName -Destination $linuxMergedLcovPath
} else {
Merge-LcovFile -Path ($linuxLcovFiles | ForEach-Object { $_.FullName }) -OutputPath $linuxMergedLcovPath -Verbose
}

$fullReport = Get-FullCodeCoverageReport -LcovPath $linuxMergedLcovPath -Verbose

"full_percentage=$($fullReport.Percentage)" | Out-File -Append -Encoding utf8 -FilePath $env:GITHUB_OUTPUT
"full_covered=$($fullReport.CoveredLines)" | Out-File -Append -Encoding utf8 -FilePath $env:GITHUB_OUTPUT
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

54 changes: 54 additions & 0 deletions dsc/tests/dsc_schema_default.tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

Describe 'Synthetic test uses schema defaults' {
It 'Property matching schema default is not reported as differing' {
$out = '{"name":"test","enabled":true}' | dsc resource test -r Test/SchemaDefault -f - | ConvertFrom-Json
$LASTEXITCODE | Should -Be 0
$out.inDesiredState | Should -Be $true
$out.differingProperties | Should -BeNullOrEmpty
}

It 'Property differing from schema default is reported as differing' {
$out = '{"name":"test","enabled":false}' | dsc resource test -r Test/SchemaDefault -f - | ConvertFrom-Json
$LASTEXITCODE | Should -Be 0
$out.inDesiredState | Should -Be $false
$out.differingProperties | Should -Contain 'enabled'
}

It 'Integer property matching schema default is not reported as differing' {
$out = '{"name":"test","count":5}' | dsc resource test -r Test/SchemaDefault -f - | ConvertFrom-Json
$LASTEXITCODE | Should -Be 0
$out.inDesiredState | Should -Be $true
$out.differingProperties | Should -BeNullOrEmpty
}

It 'Integer property differing from schema default is reported as differing' {
$out = '{"name":"test","count":10}' | dsc resource test -r Test/SchemaDefault -f - | ConvertFrom-Json
$LASTEXITCODE | Should -Be 0
$out.inDesiredState | Should -Be $false
$out.differingProperties | Should -Contain 'count'
}

It 'Multiple properties matching schema defaults are not reported as differing' {
$out = '{"name":"test","enabled":true,"count":5}' | dsc resource test -r Test/SchemaDefault -f - | ConvertFrom-Json
$LASTEXITCODE | Should -Be 0
$out.inDesiredState | Should -Be $true
$out.differingProperties | Should -BeNullOrEmpty
}

It 'Mix of matching and non-matching defaults reports only non-matching' {
$out = '{"name":"test","enabled":true,"count":10}' | dsc resource test -r Test/SchemaDefault -f - | ConvertFrom-Json
$LASTEXITCODE | Should -Be 0
$out.inDesiredState | Should -Be $false
$out.differingProperties | Should -Contain 'count'
$out.differingProperties | Should -Not -Contain 'enabled'
}

It 'Property present in both expected and actual is compared normally' {
$out = '{"name":"test"}' | dsc resource test -r Test/SchemaDefault -f - | ConvertFrom-Json
$LASTEXITCODE | Should -Be 0
$out.inDesiredState | Should -Be $true
$out.differingProperties | Should -BeNullOrEmpty
}
}
11 changes: 9 additions & 2 deletions lib/dsc-lib/src/dscresources/command_resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::{configure::{config_doc::{ExecutionKind, SecurityContextKind}, config
use crate::dscerror::DscError;
use crate::locked_insert;
use super::{
dscresource::{get_diff, redact, DscResource},
dscresource::{get_diff, get_diff_with_schema, redact, DscResource},
invoke_result::{
DeleteResult, DeleteResultKind, ExportResult,
GetResult, ResolveResult, SetResult, TestResult, ValidateResult,
Expand Down Expand Up @@ -454,7 +454,14 @@ fn invoke_synthetic_test(resource: &DscResource, expected: &str, target_resource
}
};
let expected_value: Value = serde_json::from_str(expected)?;
let diff_properties = get_diff(&expected_value, &actual_state);
let cached_resource = target_resource.unwrap_or(resource);
let schema: Option<Value> = get_resource_schema(&cached_resource.type_name, &cached_resource.version)
.or_else(|| {
// Populate the cache on a miss, then read from cache
get_schema(resource, target_resource).ok();
get_resource_schema(&cached_resource.type_name, &cached_resource.version)
});
let diff_properties = get_diff_with_schema(&expected_value, &actual_state, schema.as_ref());
Ok(TestResult::Resource(ResourceTestResponse {
desired_state: expected_value,
actual_state,
Expand Down
Loading
Loading