diff --git a/Cargo.lock b/Cargo.lock index eb571d7dd..ce032b2d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -310,9 +310,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.2.60" +version = "1.2.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" +checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" dependencies = [ "find-msvc-tools", "shlex", @@ -368,9 +368,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.6.2" +version = "4.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff7a1dccbdd8b078c2bdebff47e404615151534d5043da397ec50286816f9cb" +checksum = "e0a7a9bfdb35811f9e59832f0f05975114d2251b415fb534108e6f34060fd772" dependencies = [ "clap", ] @@ -520,7 +520,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162" dependencies = [ "dispatch2", - "nix 0.31.2", + "nix", "windows-sys 0.61.2", ] @@ -719,7 +719,7 @@ dependencies = [ [[package]] name = "dsc" -version = "3.2.1" +version = "3.2.2" dependencies = [ "clap", "clap_complete", @@ -878,7 +878,7 @@ name = "dsc-lib-security_context" version = "0.1.0" dependencies = [ "is_elevated", - "nix 0.31.2", + "nix", ] [[package]] @@ -1738,9 +1738,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.183" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "linked-hash-map" @@ -1869,21 +1869,9 @@ dependencies = [ [[package]] name = "nix" -version = "0.30.1" +version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" -dependencies = [ - "bitflags 2.9.4", - "cfg-if", - "cfg_aliases", - "libc", -] - -[[package]] -name = "nix" -version = "0.31.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" +checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" dependencies = [ "bitflags 2.9.4", "cfg-if", @@ -2104,9 +2092,9 @@ checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" [[package]] name = "objc2-foundation" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ "bitflags 2.9.4", "block2", @@ -2136,6 +2124,17 @@ dependencies = [ "objc2-core-foundation", ] +[[package]] +name = "objc2-open-directory" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb82bed227edf5201dfedf072bba4015a33d3d4a98519837295a90f0a23f676d" +dependencies = [ + "objc2", + "objc2-core-foundation", + "objc2-foundation", +] + [[package]] name = "objc2-quartz-core" version = "0.3.1" @@ -2192,13 +2191,13 @@ checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" [[package]] name = "os_info" -version = "3.14.0" +version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4022a17595a00d6a369236fdae483f0de7f0a339960a53118b818238e132224" +checksum = "9cf20a545b305cf1da722b236b5155c9bb35f1d5ceb28c048bd96ca842f41b5b" dependencies = [ "android_system_properties", "log", - "nix 0.30.1", + "nix", "objc2", "objc2-foundation", "objc2-ui-kit", @@ -2724,9 +2723,9 @@ dependencies = [ [[package]] name = "rust-i18n" -version = "4.0.0" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21031bf5e6f2c0ae745d831791c403608e99a8bd3776c7e5e5535acd70c3b7ba" +checksum = "55691a65892c33ee2de49c15ea5600c6f4a70e8eeb8e6c3cd96d2a231d230c40" dependencies = [ "globwalk", "regex", @@ -2737,9 +2736,9 @@ dependencies = [ [[package]] name = "rust-i18n-macro" -version = "4.0.0" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51fe5295763b358606f7ca26a564e20f4469775a57ec1f09431249a33849ff52" +checksum = "30de488acadcf767d97cd48518a8da8ea9777b1c9a5beca4eab78bbf77d07309" dependencies = [ "glob", "proc-macro2", @@ -2753,18 +2752,15 @@ dependencies = [ [[package]] name = "rust-i18n-support" -version = "4.0.0" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69bcc115c8eea2803aa3d85362e339776f4988a0349f2f475af572e497443f6f" +checksum = "aea0fef8a93c06326b66392c95a115120e609674cb2132d37d276a6b05b545b4" dependencies = [ "arc-swap", "base62", "globwalk", "itertools", - "lazy_static", "normpath", - "proc-macro2", - "regex", "serde", "serde_json", "serde_yaml", @@ -2892,9 +2888,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.149" +version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ "indexmap", "itoa", @@ -2959,9 +2955,9 @@ dependencies = [ [[package]] name = "shlex" -version = "1.3.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "signal-hook" @@ -3099,15 +3095,16 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.38.4" +version = "0.39.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ab6a2f8bfe508deb3c6406578252e491d299cbbf3bc0529ecc3313aee4a52f" +checksum = "21d0d938c10fcda3e897e28aaddf4ab462375d411f4378cd63b1c945f69aba96" dependencies = [ "libc", "memchr", "ntapi", "objc2-core-foundation", "objc2-io-kit", + "objc2-open-directory", "windows 0.62.2", ] @@ -3260,9 +3257,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.52.1" +version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ "bytes", "libc", @@ -3352,9 +3349,9 @@ checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "tonic" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fec7c61a0695dc1887c1b53952990f3ad2e3a31453e1f49f10e75424943a93ec" +checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef" dependencies = [ "async-trait", "axum", @@ -3381,9 +3378,9 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.14.2" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c40aaccc9f9eccf2cd82ebc111adc13030d23e887244bc9cfa5d1d636049de3" +checksum = "c68f61875ac5293cf72e6c8cf0158086428c82c37229e98c840878f1706b0322" dependencies = [ "prettyplease", "proc-macro2", @@ -3393,9 +3390,9 @@ dependencies = [ [[package]] name = "tonic-prost" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55376a0bbaa4975a3f10d009ad763d8f4108f067c7c2e74f3001fb49778d309" +checksum = "50849f68853be452acf590cde0b146665b8d507b3b8af17261df47e02c209ea0" dependencies = [ "bytes", "prost", @@ -3404,9 +3401,9 @@ dependencies = [ [[package]] name = "tonic-prost-build" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3144df636917574672e93d0f56d7edec49f90305749c668df5101751bb8f95a" +checksum = "654e5643eff75d7f8c99197ce1440ed19a3474eada74c12bbac488b2cafdae27" dependencies = [ "prettyplease", "proc-macro2", @@ -3420,9 +3417,9 @@ dependencies = [ [[package]] name = "tonic-reflection" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaf0685a51e6d02b502ba0764002e766b7f3042aed13d9234925b6ffbfa3fca7" +checksum = "acccd136a4bf19810a1fde9c74edc6129b42a66b44d0c1c8aaa67aeb49a146a7" dependencies = [ "prost", "prost-types", @@ -3569,9 +3566,9 @@ dependencies = [ [[package]] name = "tree-sitter" -version = "0.26.8" +version = "0.26.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "887bd495d0582c5e3e0d8ece2233666169fa56a9644d172fc22ad179ab2d0538" +checksum = "4dab76d0b724ba557954125188cf0633a1ca43199ced82d95c7b9c32cc3de1f3" dependencies = [ "cc", "regex", @@ -3733,9 +3730,9 @@ checksum = "133bf74f01486773317ddfcde8e2e20d2933cc3b68ab797e5d718bef996a81de" [[package]] name = "uuid" -version = "1.23.1" +version = "1.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" +checksum = "d258b83ceec21034727ecee8c382cfa6c3e133699b0742c64571814fb420c9f7" dependencies = [ "getrandom 0.4.1", "js-sys", diff --git a/Cargo.toml b/Cargo.toml index b91de8564..8cd43fe4b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -153,7 +153,7 @@ chrono = { version = "0.4.44" } # dsc, dsc-lib, dsc-bicep-ext, dscecho, registry, runcommandonset, sshdconfig, dsctest, test_group_resource clap = { version = "4.6.1", features = ["derive"] } # dsc -clap_complete = { version = "4.6.2" } +clap_complete = { version = "4.6.5" } # dsc-lib const-str = {version = "1.1" } # dsc, registry, dsc-lib-registry, sshdconfig @@ -179,11 +179,11 @@ miette = { version = "7.6.0" } # dsc-lib murmurhash64 = { version = "0.3" } # dsc-lib-security_context::not_windows -nix = { version = "0.31" } +nix = { version = "0.31.3" } # dsc-lib num-traits = { version = "0.2" } # dsc-lib-osinfo -os_info = { version = "3.14" } +os_info = { version = "3.15.0" } # dsc, dsc-lib path-absolutize = { version = "3.1" } # dsc-bicep-ext @@ -201,7 +201,7 @@ rmcp = { version = "1.5.0" } # dsc_lib rt-format = { version = "0.3" } # dsc, dsc-lib, dsc-bicep-ext, dscecho, registry, dsc-lib-registry, runcommandonset, sshdconfig -rust-i18n = { version = "4.0.0" } +rust-i18n = { version = "4.1.0" } # dsc, dsc-lib, dscecho, registry, dsc-lib-registry, sshdconfig, dsctest, test_group_resource schemars = { version = "1.2.1", features = ["preserve_order"] } # dsc, dsc-lib @@ -209,7 +209,7 @@ semver = { version = "1.0.28" } # dsc, dsc-lib, dscecho, dsc-lib-osinfo, process, registry, dsc-lib-registry, runcommandonset, sshdconfig, dsctest, test_group_resource serde = { version = "1.0", features = ["derive"] } # dsc, dsc-lib, dscecho, dsc-lib-osinfo, osinfo, process, registry, dsc-lib-registry, runcommandonset, sshdconfig, dsctest, test_group_resource, y2j -serde_json = { version = "1.0.149", features = ["preserve_order"] } +serde_json = { version = "1.0.150", features = ["preserve_order"] } # dsc, dsc-lib, y2j serde_yaml = { version = "0.9" } # dsc-lib-jsonschema-macros @@ -217,23 +217,23 @@ syn = { version = "2.0" } # dsc, y2j syntect = { version = "5.3", features = ["default-fancy"], default-features = false } # dsc, process -sysinfo = { version = "0.38.4" } +sysinfo = { version = "0.39.3" } # sshdconfig tempfile = { version = "3.27" } # dsc, dsc-lib, registry, dsc-lib-registry, sshdconfig thiserror = { version = "2.0.18" } # dsc, dsc-lib, dsc-bicep-ext -tokio = { version = "1.52.1" } +tokio = { version = "1.52.3" } # dsc-bicep-ext tokio-stream = { version = "0.1.18" } # dsc tokio-util = { version = "0.7.18" } # dsc-bicep-ext -tonic = { version = "0.14.5" } +tonic = { version = "0.14.6" } # dsc-bicep-ext -tonic-prost = { version = "0.14.5" } +tonic-prost = { version = "0.14.6" } # dsc-bicep-ext -tonic-reflection = { version = "0.14.5" } +tonic-reflection = { version = "0.14.6" } # dsc, dsc-lib, dsc-bicep-ext, registry, dsc-lib-registry, runcommandonset, sshdconfig tracing = { version = "0.1.44" } # dsc, dsc-lib @@ -241,7 +241,7 @@ tracing-indicatif = { version = "0.3.14" } # dsc, dsc-bicep-ext, registry, dsc-lib-registry, runcommandonset, sshdconfig tracing-subscriber = { version = "0.3.23", features = ["ansi", "env-filter", "json"] } # dsc-lib, sshdconfig, tree-sitter-dscexpression, tree-sitter-ssh-server-config -tree-sitter = { version = "0.26.8" } +tree-sitter = { version = "0.26.9" } # tree-sitter-dscexpression, tree-sitter-ssh-server-config tree-sitter-language = { version = "0.1.7" } # dsc-lib, sshdconfig, tree-sitter-dscexpression, tree-sitter-ssh-server-config @@ -249,7 +249,7 @@ tree-sitter-rust = { version = "0.24.2" } # registry, dsc-lib-registry, dsctest utfx = { version = "0.1" } # dsc-lib -uuid = { version = "1.23.1", features = ["v4"] } +uuid = { version = "1.23.2", features = ["v4"] } # dsc-lib, dsc-lib-jsonschema url = { version = "2.5.8" } # dsc-lib, dsc-lib-jsonschema @@ -271,9 +271,9 @@ windows = { version = "0.62", features = [ # build-only dependencies # dsc-lib, dsc-lib-registry, sshdconfig, tree-sitter-dscexpression, tree-sitter-ssh-server-config -cc = { version = "1.2.60" } +cc = { version = "1.2.63" } # dsc -tonic-prost-build = { version = "0.14" } +tonic-prost-build = { version = "0.14.6" } # test-only dependencies # dsc-lib-jsonschema, dsc-lib diff --git a/build.ps1 b/build.ps1 index 7f79e29f3..57591ee1e 100755 --- a/build.ps1 +++ b/build.ps1 @@ -89,6 +89,7 @@ param( [switch]$Test, [string[]]$Project, [switch]$ExcludeRustTests, + [string]$RustTestFilter, [switch]$ExcludePesterTests, [ValidateSet("dsc", "adapters", "extensions", "grammars", "resources")] [string[]]$PesterTestGroup, @@ -266,6 +267,9 @@ process { Architecture = $Architecture Release = $Release } + if (-not [string]::IsNullOrEmpty($RustTestFilter)) { + $rustTestParams.TestFilter = $RustTestFilter + } Write-BuildProgress @progressParams -Status "Testing Rust projects" Test-RustProject @rustTestParams @VerboseParam } diff --git a/dsc/Cargo.toml b/dsc/Cargo.toml index 6c6c0ce45..7b3f6d821 100644 --- a/dsc/Cargo.toml +++ b/dsc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dsc" -version = "3.2.1" +version = "3.2.2" edition = "2024" [dependencies] diff --git a/helpers.build.psm1 b/helpers.build.psm1 index 571a6cc8b..e56d10b3b 100644 --- a/helpers.build.psm1 +++ b/helpers.build.psm1 @@ -1798,7 +1798,8 @@ function Test-RustProject { [ValidateSet('current','aarch64-pc-windows-msvc','x86_64-pc-windows-msvc','aarch64-apple-darwin','x86_64-apple-darwin','aarch64-unknown-linux-gnu','aarch64-unknown-linux-musl','x86_64-unknown-linux-gnu','x86_64-unknown-linux-musl')] $Architecture = 'current', [switch]$Release, - [switch]$Docs + [switch]$Docs, + [string]$TestFilter ) begin { @@ -1828,7 +1829,11 @@ function Test-RustProject { } else { Write-Verbose -Verbose "Testing rust projects: [$members]" } - cargo test @flags + if (-not [string]::IsNullOrEmpty($TestFilter)) { + cargo test @flags -- $TestFilter + } else { + cargo test @flags + } if ($null -ne $LASTEXITCODE -and $LASTEXITCODE -ne 0) { Write-Error "Last exit code is $LASTEXITCODE, rust tests failed" diff --git a/lib/dsc-lib/src/dscresources/command_resource.rs b/lib/dsc-lib/src/dscresources/command_resource.rs index 3508cff88..c03525ab6 100644 --- a/lib/dsc-lib/src/dscresources/command_resource.rs +++ b/lib/dsc-lib/src/dscresources/command_resource.rs @@ -767,6 +767,8 @@ async fn run_process_async(executable: &str, args: Option>, input: O let mut command = Command::new(executable); if input.is_some() { command.stdin(Stdio::piped()); + } else { + command.stdin(Stdio::null()); } command.stdout(Stdio::piped()); command.stderr(Stdio::piped()); diff --git a/lib/dsc-lib/tests/integration/command_resource.rs b/lib/dsc-lib/tests/integration/command_resource.rs new file mode 100644 index 000000000..6f87c88b8 --- /dev/null +++ b/lib/dsc-lib/tests/integration/command_resource.rs @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#[cfg(test)] +mod invoke_command { + use dsc_lib::{dscresources::command_resource::invoke_command, types::ExitCodesMap}; + + /// Verifies that when `invoke_command` is called with `input = None`, the child process + /// receives an immediate EOF on stdin (i.e., stdin is set to null) rather than inheriting + /// the parent's stdin handle. + /// + /// This is a regression test for the hang introduced in DSC 3.2.0 when the PowerShell + /// adapter changed from `"config": "full"` to `"config": "single"`. In single mode, the + /// adapter's export operation is called with no input, leaving stdin unset in the previous + /// code. Child processes that read from stdin would then block indefinitely when the parent + /// process itself had an open stdin handle — either a TTY in a terminal or a pipe in CI. + /// + /// The test uses a timed async read rather than a blocking read so that the child process + /// always exits within a bounded time. If stdin is null (the fix), `ReadAsync` completes + /// immediately returning 0 bytes (EOF), which maps to -1. If stdin is inherited (the bug), + /// `ReadAsync` blocks until the timeout fires and the test receives -2, which fails the + /// assertion. + #[test] + fn no_input_does_not_block_on_stdin() { + let exit_codes = ExitCodesMap::default(); + + // Use PowerShell's own async timeout so the child process always exits within ~2s, + // regardless of fix status. We never leave a hanging thread: + // byte:-1 → ReadAsync got EOF immediately → stdin was null → PASS + // byte:-2 → ReadAsync timed out (2 s) → stdin was NOT null → FAIL + let ps_command = concat!( + "$reader = [Console]::OpenStandardInput();", + "$buf = [byte[]]::new(1);", + "$task = $reader.ReadAsync($buf, 0, 1);", + "$completed = $task.Wait(2000);", + "$b = if ($completed) { if ($task.Result -eq 0) { -1 } else { $buf[0] } } else { -2 };", + "Write-Output \"byte:$b\"" + ); + + let result = invoke_command( + "pwsh", + Some(vec![ + "-NonInteractive".to_string(), + "-NoProfile".to_string(), + "-Command".to_string(), + ps_command.to_string(), + ]), + None, // no input — the scenario that caused the hang + None, + None, + &exit_codes, + ).expect("invoke_command should succeed"); + + let (exit_code, stdout, _stderr) = result; + assert_eq!(exit_code, 0, "Command should exit 0"); + // -1 means ReadAsync got EOF immediately, confirming stdin was set to null. + // -2 means stdin was open (inherited) and the read timed out after 2s. + assert!( + stdout.contains("byte:-1"), + "Expected EOF (byte:-1) from null stdin, got: {stdout:?}\n\ + 'byte:-2' means stdin was inherited from the parent rather than set to null." + ); + } +} diff --git a/lib/dsc-lib/tests/integration/main.rs b/lib/dsc-lib/tests/integration/main.rs index 28aca9416..3a005a0ac 100644 --- a/lib/dsc-lib/tests/integration/main.rs +++ b/lib/dsc-lib/tests/integration/main.rs @@ -13,5 +13,6 @@ //! minimize compilation times. If we defined the tests one level higher in the `tests` folder, //! Rust would generate numerous binaries to execute our tests. +#[cfg(test)] mod command_resource; #[cfg(test)] mod schemas; #[cfg(test)] mod types; diff --git a/resources/PSScript/psscript.ps1 b/resources/PSScript/psscript.ps1 index 2b395dce1..e3d562abb 100644 --- a/resources/PSScript/psscript.ps1 +++ b/resources/PSScript/psscript.ps1 @@ -138,17 +138,32 @@ try { $asyncResult = $ps.BeginInvoke() while (-not $asyncResult.IsCompleted) { Write-TraceQueue - + Start-Sleep -Milliseconds 100 } + + if ($ps.InvocationStateInfo.State -eq 'Failed') { + $record = $ps.InvocationStateInfo.Reason.ErrorRecord + $message = if ($null -ne $record) { + "Script failed with terminating error at line {0} for statement ``{1}`` - {2}" -f @( + $record.InvocationInfo.ScriptLineNumber, + $record.InvocationInfo.Line, + $record.Exception.ToString() + ) + } else { + "Script failed with terminating error: $($ps.InvocationStateInfo.Reason)" + } + Write-DscTrace -Now -Level Error -Message $message + exit 1 + } + $outputCollection = $ps.EndInvoke($asyncResult) Write-TraceQueue if ($ps.HadErrors) { - # If there are any errors, we will exit with an error code - Write-DscTrace -Now -Level Error -Message 'Errors occurred during script execution.' - exit 1 + # Errors can be non-terminating, so we just write a warning and continue + Write-DscTrace -Now -Level Debug -Message 'Non-terminating errors occurred during script execution.' } foreach ($output in $outputCollection) { @@ -156,7 +171,7 @@ try { } } catch { - Write-DscTrace -Now -Level Error -Message $_ + Write-DscTrace -Now -Level Error -Message ($_ | Format-List -Force * | Out-String) exit 1 } finally { diff --git a/resources/PSScript/psscript.tests.ps1 b/resources/PSScript/psscript.tests.ps1 index 4406ccae5..b2d91786d 100644 --- a/resources/PSScript/psscript.tests.ps1 +++ b/resources/PSScript/psscript.tests.ps1 @@ -108,7 +108,8 @@ Describe 'Tests for PSScript resource' { $result = dsc resource test -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json $LASTEXITCODE | Should -Be 2 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String) $result | Should -BeNullOrEmpty -Because "Test operation should return an error" - (Get-Content $TestDrive/error.txt -Raw) | Should -BeLike '*Test operation did not return a single boolean value.*' + $errorLog = Get-Content $TestDrive/error.txt -Raw + $errorLog | Should -BeLike '*ERROR*:*Test operation did not return a single boolean value.*' -Because $errorLog } It 'Test operation returns error for multiple boolean results for ' -TestCases $testCases { @@ -122,7 +123,8 @@ Describe 'Tests for PSScript resource' { $result = dsc resource test -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json $LASTEXITCODE | Should -Be 2 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String) $result | Should -BeNullOrEmpty -Because "Test operation should return an error" - (Get-Content $TestDrive/error.txt -Raw) | Should -BeLike '*Test operation did not return a single boolean value.*' + $errorLog = Get-Content $TestDrive/error.txt -Raw + $errorLog | Should -BeLike '*ERROR*:*Test operation did not return a single boolean value.*' -Because $errorLog } It 'Empty SetScript is ignored for ' -TestCases $testCases { @@ -187,8 +189,9 @@ Describe 'Tests for PSScript resource' { $result = dsc resource get -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json $LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String) $result.actualState.output.Count | Should -Be 0 -Because ($result | ConvertTo-Json | Out-String) - (Get-Content $TestDrive/error.txt -Raw) | Should -BeLike '*WARN*:*This is a warning*' - (Get-Content $TestDrive/error.txt -Raw) | Should -BeLike '*WARN*:*This is second warning*' + $errorLog = Get-Content $TestDrive/error.txt -Raw + $errorLog | Should -BeLike '*WARN*:*This is a warning*' -Because $errorLog + $errorLog | Should -BeLike '*WARN*:*This is second warning*' -Because $errorLog } It 'Write-Error shows up as error traces for ' -TestCases $testCases { @@ -201,8 +204,9 @@ Describe 'Tests for PSScript resource' { $result = dsc resource get -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json $LASTEXITCODE | Should -Be 2 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String) + $errorLog = Get-Content $TestDrive/error.txt -Raw $result.actualState.output.Count | Should -Be 0 -Because ($result | ConvertTo-Json | Out-String) - (Get-Content $TestDrive/error.txt -Raw) | Should -BeLike '*ERROR*:*This is an error*' + $errorLog | Should -BeLike '*ERROR*:*This is an error*' -Because $errorLog } It 'Write-Verbose shows up as info traces for ' -TestCases $testCases { @@ -214,8 +218,9 @@ Describe 'Tests for PSScript resource' { '@ $result = dsc -l info resource get -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json $LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String) + $errorLog = Get-Content $TestDrive/error.txt -Raw $result.actualState.output.Count | Should -Be 0 -Because ($result | ConvertTo-Json | Out-String) - (Get-Content $TestDrive/error.txt -Raw) | Should -BeLike '*INFO*:*This is a verbose message*' + $errorLog | Should -BeLike '*INFO*:*This is a verbose message*' -Because $errorLog } It 'Write-Debug shows up as debug traces for ' -TestCases $testCases { @@ -227,8 +232,9 @@ Describe 'Tests for PSScript resource' { '@ $result = dsc -l debug resource get -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json $LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String) + $errorLog = Get-Content $TestDrive/error.txt -Raw $result.actualState.output.Count | Should -Be 0 -Because ($result | ConvertTo-Json | Out-String) - (Get-Content $TestDrive/error.txt -Raw) | Should -BeLike '*DEBUG*:*This is a debug message*' + $errorLog | Should -BeLike '*DEBUG*:*This is a debug message*' -Because $errorLog } It 'Write-Information shows up as trace traces for ' -TestCases $testCases { @@ -241,8 +247,9 @@ Describe 'Tests for PSScript resource' { '@ $result = dsc -l trace resource get -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json $LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String) + $errorLog = Get-Content $TestDrive/error.txt -Raw $result.actualState.output.Count | Should -Be 0 -Because ($result | ConvertTo-Json | Out-String) - (Get-Content $TestDrive/error.txt -Raw) | Should -BeLike '*TRACE*:*This is an information message*' + $errorLog | Should -BeLike '*TRACE*:*This is an information message*' -Because $errorLog } It 'A thrown exception results in an error for ' -TestCases $testCases { @@ -254,8 +261,9 @@ Describe 'Tests for PSScript resource' { '@ $result = dsc resource get -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json $LASTEXITCODE | Should -Be 2 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String) + $errorLog = Get-Content $TestDrive/error.txt -Raw $result.actualState.output.Count | Should -Be 0 -Because ($result | ConvertTo-Json | Out-String) - (Get-Content $TestDrive/error.txt -Raw) | Should -BeLike '*ERROR*:*This is an exception*' + $errorLog | Should -BeLike '*ERROR*:*This is an exception*' -Because $errorLog } It 'Sample config works' { @@ -291,8 +299,9 @@ Describe 'Tests for PSScript resource' { input: "This is a string" '@ dsc resource get -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json - $LASTEXITCODE | Should -Be 2 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String) - (Get-Content $TestDrive/error.txt -Raw) | Should -BeLike '*ERROR*:*Input was provided but script does not have a parameter to accept input.*' + $errorLog = Get-Content $TestDrive/error.txt -Raw + $LASTEXITCODE | Should -Be 2 -Because $errorLog + $errorLog | Should -BeLike '*ERROR*:*Input was provided but script does not have a parameter to accept input.*' -Because $errorLog } It 'Param without input is an error for ' -TestCases $testCases { @@ -304,8 +313,9 @@ Describe 'Tests for PSScript resource' { "This should fail" '@ dsc resource get -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json - $LASTEXITCODE | Should -Be 2 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String) - (Get-Content $TestDrive/error.txt -Raw) | Should -BeLike "*ERROR*:*Script has a parameter 'inputObj' but no input was provided.*" + $errorLog = Get-Content $TestDrive/error.txt -Raw + $LASTEXITCODE | Should -Be 2 -Because $errorLog + $errorLog | Should -BeLike "*ERROR*:*Script has a parameter 'inputObj' but no input was provided.*" -Because $errorLog } It 'Write-Host results in an info message for ' -TestCases $testCases { @@ -319,9 +329,39 @@ Describe 'Tests for PSScript resource' { '@ $result = dsc -l trace resource get -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json $LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String) + $errorLog = Get-Content $TestDrive/error.txt -Raw + $result.actualState.output.Count | Should -Be 0 -Because ($result | ConvertTo-Json | Out-String) + $errorLog | Should -BeLike '*WARN*:*This is a warning*' -Because $errorLog + $errorLog | Should -BeLike '*INFO*:*This is a host message*' -Because $errorLog + $errorLog | Should -BeLike '*INFO*:*This is a verbose message*' -Because $errorLog + } + + It 'Non-terminating errors do not cause script to fail' -TestCases $testCases { + param($resourceType) + + $yaml = @' + getScript: | + Get-Item "ThisFileDoesNotExist.txt" -ErrorAction SilentlyContinue + "This should still be output" +'@ + $result = dsc -l debug resource get -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json + $LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String) + $result.actualState.output.Count | Should -Be 1 -Because ($result | ConvertTo-Json -Depth 10 | Out-String) + $result.actualState.output[0] | Should -BeExactly "This should still be output" + $errorLog = Get-Content $TestDrive/error.txt -Raw + $errorLog | Should -BeLike '*DEBUG*:*Non-terminating errors occurred during script execution.*' -Because $errorLog + } + + It 'Terminating errors result in an error for ' -TestCases $testCases { + param($resourceType) + + $yaml = @' + GetScript: | + Get-Item "ThisFileDoesNotExist.txt" -ErrorAction Stop +'@ + $result = dsc resource get -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json + $LASTEXITCODE | Should -Be 2 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String) $result.actualState.output.Count | Should -Be 0 -Because ($result | ConvertTo-Json | Out-String) - (Get-Content $TestDrive/error.txt -Raw) | Should -BeLike '*WARN*:*This is a warning*' - (Get-Content $TestDrive/error.txt -Raw) | Should -BeLike '*INFO*:*This is a host message*' - (Get-Content $TestDrive/error.txt -Raw) | Should -BeLike '*INFO*:*This is a verbose message*' + (Get-Content $TestDrive/error.txt -Raw) | Should -BeLike '*ERROR*:*Cannot find path*' } } diff --git a/resources/WindowsUpdate/tests/windowsupdate_export.tests.ps1 b/resources/WindowsUpdate/tests/windowsupdate_export.tests.ps1 index c12a3a54b..e043c384c 100644 --- a/resources/WindowsUpdate/tests/windowsupdate_export.tests.ps1 +++ b/resources/WindowsUpdate/tests/windowsupdate_export.tests.ps1 @@ -8,7 +8,7 @@ Describe 'Windows Update Export operation tests' { Context 'Export operation' { It 'should return UpdateList with array of updates' -Skip:(!$IsWindows) { - $out = '{"updates":[{}]}' | dsc resource export -r $resourceType -o json 2>&1 + $out = '{"updates":[{}]}' | dsc resource export -r $resourceType -f - -o json 2>&1 $LASTEXITCODE | Should -Be 0 $config = $out | ConvertFrom-Json @@ -18,7 +18,7 @@ Describe 'Windows Update Export operation tests' { } It 'should work without input filter' -Skip:(!$IsWindows) { - $out = '' | dsc resource export -r $resourceType -o json 2>&1 + $out = dsc resource export -r $resourceType -o json 2>&1 $LASTEXITCODE | Should -Be 0 $config = $out | ConvertFrom-Json @@ -28,7 +28,7 @@ Describe 'Windows Update Export operation tests' { It 'should filter by isInstalled=true' -Skip:(!$IsWindows) { $json = '{"updates":[{"isInstalled": true}]}' - $out = $json | dsc resource export -r $resourceType -o json 2>&1 + $out = $json | dsc resource export -r $resourceType -f - -o json 2>&1 $LASTEXITCODE | Should -Be 0 $config = $out | ConvertFrom-Json @@ -42,7 +42,7 @@ Describe 'Windows Update Export operation tests' { It 'should filter by isInstalled=false' -Skip:(!$IsWindows) { $json = '{"updates":[{"isInstalled": false}]}' - $out = $json | dsc resource export -r $resourceType -o json 2>&1 + $out = $json | dsc resource export -r $resourceType -f - -o json 2>&1 $LASTEXITCODE | Should -Be 0 $config = $out | ConvertFrom-Json @@ -56,7 +56,7 @@ Describe 'Windows Update Export operation tests' { It 'should filter by title with wildcard in middle' -Skip:(!$IsWindows) { $json = '{"updates":[{"title": "*Windows*"}]}' - $out = $json | dsc resource export -r $resourceType -o json 2>&1 + $out = $json | dsc resource export -r $resourceType -f - -o json 2>&1 if ($LASTEXITCODE -eq 0) { $config = $out | ConvertFrom-Json @@ -70,7 +70,7 @@ Describe 'Windows Update Export operation tests' { } It 'should return proper structure for each update' -Skip:(!$IsWindows) { - $out = '{"updates":[{}]}' | dsc resource export -r $resourceType -o json 2>&1 + $out = '{"updates":[{}]}' | dsc resource export -r $resourceType -f - -o json 2>&1 $LASTEXITCODE | Should -Be 0 $config = $out | ConvertFrom-Json @@ -92,7 +92,7 @@ Describe 'Windows Update Export operation tests' { It 'should fail when wildcard filter has no matches' -Skip:(!$IsWindows) { $json = '{"updates":[{"title": "ThisUpdateShouldNeverExist99999*"}]}' - $stderr = $json | dsc resource export -r $resourceType -o json 2>&1 + $stderr = $json | dsc resource export -r $resourceType -f - -o json 2>&1 # Should fail because the filter has criteria but no matches $LASTEXITCODE | Should -Not -Be 0 @@ -111,7 +111,7 @@ Describe 'Windows Update Export operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $stderr = $json | dsc resource export -r $resourceType 2>&1 + $stderr = $json | dsc resource export -r $resourceType -f - 2>&1 # Should fail because the filter has criteria but no matches $LASTEXITCODE | Should -Not -Be 0 @@ -128,7 +128,7 @@ Describe 'Windows Update Export operation tests' { @{} ) } | ConvertTo-Json -Depth 10 -Compress - $out = $json | dsc resource export -r $resourceType -o json 2>&1 + $out = $json | dsc resource export -r $resourceType -f - -o json 2>&1 $LASTEXITCODE | Should -Be 0 $config = $out | ConvertFrom-Json @@ -138,7 +138,7 @@ Describe 'Windows Update Export operation tests' { It 'should fail if any filter with criteria has no matches' -Skip:(!$IsWindows) { # Get an actual update - $allOut = '{"updates":[{}]}' | dsc resource export -r $resourceType -o json 2>&1 + $allOut = '{"updates":[{}]}' | dsc resource export -r $resourceType -f - -o json 2>&1 if ($LASTEXITCODE -eq 0) { $allConfig = $allOut | ConvertFrom-Json @@ -157,7 +157,7 @@ Describe 'Windows Update Export operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $stderr = $json | dsc resource export -r $resourceType 2>&1 + $stderr = $json | dsc resource export -r $resourceType -f - 2>&1 # Should fail because second filter has no matches $LASTEXITCODE | Should -Not -Be 0 @@ -171,7 +171,7 @@ Describe 'Windows Update Export operation tests' { It 'should return results when all filters find matches' -Skip:(!$IsWindows) { # Get actual updates - $allOut = '{"updates":[{}]}' | dsc resource export -r $resourceType -o json 2>&1 + $allOut = '{"updates":[{}]}' | dsc resource export -r $resourceType -f - -o json 2>&1 if ($LASTEXITCODE -eq 0) { $allConfig = $allOut | ConvertFrom-Json @@ -190,7 +190,7 @@ Describe 'Windows Update Export operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $out = $json | dsc resource export -r $resourceType -o json 2>&1 + $out = $json | dsc resource export -r $resourceType -f - -o json 2>&1 $LASTEXITCODE | Should -Be 0 $config = $out | ConvertFrom-Json @@ -205,7 +205,7 @@ Describe 'Windows Update Export operation tests' { It 'should filter by msrcSeverity' -Skip:(!$IsWindows) { $json = '{"updates":[{"msrcSeverity": "Critical"}]}' - $out = $json | dsc resource export -r $resourceType -o json 2>&1 + $out = $json | dsc resource export -r $resourceType -f - -o json 2>&1 if ($LASTEXITCODE -eq 0) { $config = $out | ConvertFrom-Json @@ -220,7 +220,7 @@ Describe 'Windows Update Export operation tests' { It 'should filter by updateType Software' -Skip:(!$IsWindows) { $json = '{"updates":[{"updateType": "Software"}]}' - $out = $json | dsc resource export -r $resourceType -o json 2>&1 + $out = $json | dsc resource export -r $resourceType -f - -o json 2>&1 if ($LASTEXITCODE -eq 0) { $config = $out | ConvertFrom-Json @@ -235,7 +235,7 @@ Describe 'Windows Update Export operation tests' { It 'should support OR logic with multiple filters in array' -Skip:(!$IsWindows) { # Get some updates to use as filters - $allOut = '{"updates":[{}]}' | dsc resource export -r $resourceType -o json 2>&1 + $allOut = '{"updates":[{}]}' | dsc resource export -r $resourceType -f - -o json 2>&1 if ($LASTEXITCODE -eq 0) { $allConfig = $allOut | ConvertFrom-Json @@ -245,7 +245,7 @@ Describe 'Windows Update Export operation tests' { $id1 = $allResult.updates[0].id $id2 = $allResult.updates[1].id $json = "{`"updates`":[{`"id`": `"$id1`"}, {`"id`": `"$id2`"}]}" - $out = $json | dsc resource export -r $resourceType -o json 2>&1 + $out = $json | dsc resource export -r $resourceType -f - -o json 2>&1 $LASTEXITCODE | Should -Be 0 $config = $out | ConvertFrom-Json @@ -267,7 +267,7 @@ Describe 'Windows Update Export operation tests' { It 'should support AND logic within single filter object' -Skip:(!$IsWindows) { # Multiple properties in one filter = AND logic $json = '{"updates":[{"isInstalled": true, "updateType": "Software"}]}' - $out = $json | dsc resource export -r $resourceType -o json 2>&1 + $out = $json | dsc resource export -r $resourceType -f - -o json 2>&1 if ($LASTEXITCODE -eq 0) { $config = $out | ConvertFrom-Json @@ -284,7 +284,7 @@ Describe 'Windows Update Export operation tests' { It 'should not return duplicates when multiple filters match same update' -Skip:(!$IsWindows) { # Get an update with known properties - $allOut = '{"updates":[{}]}' | dsc resource export -r $resourceType -o json 2>&1 + $allOut = '{"updates":[{}]}' | dsc resource export -r $resourceType -f - -o json 2>&1 if ($LASTEXITCODE -eq 0) { $allConfig = $allOut | ConvertFrom-Json @@ -294,7 +294,7 @@ Describe 'Windows Update Export operation tests' { # Use the same ID in both filters - this should only return one update # Even though technically both filters specify the same criteria $json = "{`"updates`":[{`"id`": `"$($testUpdate.id)`"}, {`"id`": `"$($testUpdate.id)`"}]}" - $out = $json | dsc resource export -r $resourceType -o json 2>&1 + $out = $json | dsc resource export -r $resourceType -f - -o json 2>&1 $LASTEXITCODE | Should -Be 0 -Because $out $config = $out | ConvertFrom-Json @@ -308,7 +308,7 @@ Describe 'Windows Update Export operation tests' { } It 'should return installationBehavior property when present' -Skip:(!$IsWindows) { - $out = '{"updates":[{}]}' | dsc resource export -r $resourceType -o json 2>&1 + $out = '{"updates":[{}]}' | dsc resource export -r $resourceType -f - -o json 2>&1 $LASTEXITCODE | Should -Be 0 $config = $out | ConvertFrom-Json @@ -326,7 +326,7 @@ Describe 'Windows Update Export operation tests' { } It 'should return valid installationBehavior enum values for all updates' -Skip:(!$IsWindows) { - $out = '{"updates":[{}]}' | dsc resource export -r $resourceType -o json 2>&1 + $out = '{"updates":[{}]}' | dsc resource export -r $resourceType -f - -o json 2>&1 $LASTEXITCODE | Should -Be 0 $config = $out | ConvertFrom-Json diff --git a/resources/WindowsUpdate/tests/windowsupdate_get.tests.ps1 b/resources/WindowsUpdate/tests/windowsupdate_get.tests.ps1 index ffba6b2c2..cb9f8b41c 100644 --- a/resources/WindowsUpdate/tests/windowsupdate_get.tests.ps1 +++ b/resources/WindowsUpdate/tests/windowsupdate_get.tests.ps1 @@ -20,7 +20,7 @@ Describe 'Windows Update Get operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $out = $json | dsc resource get -r $resourceType 2>&1 + $out = $json | dsc resource get -r $resourceType -f - 2>&1 $LASTEXITCODE | Should -Be 0 $getResult = $out | ConvertFrom-Json @@ -45,7 +45,7 @@ Describe 'Windows Update Get operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $outLower = $jsonLower | dsc resource get -r $resourceType 2>&1 + $outLower = $jsonLower | dsc resource get -r $resourceType -f - 2>&1 # Test with uppercase version $jsonUpper = @{ @@ -55,7 +55,7 @@ Describe 'Windows Update Get operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $outUpper = $jsonUpper | dsc resource get -r $resourceType 2>&1 + $outUpper = $jsonUpper | dsc resource get -r $resourceType -f - 2>&1 # Both should succeed if ($outLower -and $outUpper) { @@ -74,7 +74,7 @@ Describe 'Windows Update Get operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $null = $json | dsc resource get -r $resourceType 2>&1 + $null = $json | dsc resource get -r $resourceType -f - 2>&1 # This will likely fail unless there's an update with exact title "Windows" # which is unlikely $LASTEXITCODE | Should -Not -Be 0 @@ -89,7 +89,7 @@ Describe 'Windows Update Get operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $null = $json | dsc resource get -r $resourceType 2>&1 + $null = $json | dsc resource get -r $resourceType -f - 2>&1 $LASTEXITCODE | Should -Not -Be 0 } @@ -103,7 +103,7 @@ Describe 'Windows Update Get operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $out = $json | dsc resource get -r $resourceType 2>&1 + $out = $json | dsc resource get -r $resourceType -f - 2>&1 $LASTEXITCODE | Should -Be 0 $result = $out | ConvertFrom-Json @@ -121,7 +121,7 @@ Describe 'Windows Update Get operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $null = $json | dsc resource get -r $resourceType 2>&1 + $null = $json | dsc resource get -r $resourceType -f - 2>&1 # Should fail because id doesn't match $LASTEXITCODE | Should -Not -Be 0 @@ -137,7 +137,7 @@ Describe 'Windows Update Get operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $null = $json | dsc resource get -r $resourceType 2>&1 + $null = $json | dsc resource get -r $resourceType -f - 2>&1 # Should fail because title doesn't match $LASTEXITCODE | Should -Not -Be 0 @@ -151,7 +151,7 @@ Describe 'Windows Update Get operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $out = $json | dsc resource get -r $resourceType 2>&1 + $out = $json | dsc resource get -r $resourceType -f - 2>&1 $LASTEXITCODE | Should -Be 0 $result = $out | ConvertFrom-Json $result.actualState.updates[0].isInstalled | Should -BeOfType [bool] @@ -165,7 +165,7 @@ Describe 'Windows Update Get operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $out = $json | dsc resource get -r $resourceType 2>&1 + $out = $json | dsc resource get -r $resourceType -f - 2>&1 $LASTEXITCODE | Should -Be 0 $result = $out | ConvertFrom-Json $result.actualState.updates[0].recommendedHardDiskSpace | Should -BeGreaterOrEqual 0 @@ -179,7 +179,7 @@ Describe 'Windows Update Get operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $out = $json | dsc resource get -r $resourceType 2>&1 + $out = $json | dsc resource get -r $resourceType -f - 2>&1 $LASTEXITCODE | Should -Be 0 $result = $out | ConvertFrom-Json $result.actualState.updates[0].kbArticleIds.GetType().BaseType.Name | Should -Be 'Array' @@ -193,7 +193,7 @@ Describe 'Windows Update Get operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $out = $json | dsc resource get -r $resourceType 2>&1 + $out = $json | dsc resource get -r $resourceType -f - 2>&1 $LASTEXITCODE | Should -Be 0 $result = $out | ConvertFrom-Json $result.actualState.updates[0].updateType | Should -BeIn @('Software', 'Driver') @@ -210,7 +210,7 @@ Describe 'Windows Update Get operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $out = $json | dsc resource get -r $resourceType 2>&1 + $out = $json | dsc resource get -r $resourceType -f - 2>&1 $LASTEXITCODE | Should -Be 0 $result = $out | ConvertFrom-Json $result.actualState.updates[0].msrcSeverity | Should -BeExactly $updateWithSeverity.msrcSeverity @@ -225,7 +225,7 @@ Describe 'Windows Update Get operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $out = $json | dsc resource get -r $resourceType 2>&1 + $out = $json | dsc resource get -r $resourceType -f - 2>&1 $LASTEXITCODE | Should -Be 0 $result = $out | ConvertFrom-Json @@ -242,7 +242,7 @@ Describe 'Windows Update Get operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $out = $json | dsc resource get -r $resourceType 2>&1 + $out = $json | dsc resource get -r $resourceType -f - 2>&1 $LASTEXITCODE | Should -Be 0 $result = $out | ConvertFrom-Json @@ -265,7 +265,7 @@ Describe 'Windows Update Get operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $out = $json | dsc resource get -r $resourceType 2>&1 + $out = $json | dsc resource get -r $resourceType -f - 2>&1 $LASTEXITCODE | Should -Be 0 $getResult = $out | ConvertFrom-Json @@ -290,7 +290,7 @@ Describe 'Windows Update Get operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $stderr = $json | dsc resource get -r $resourceType 2>&1 + $stderr = $json | dsc resource get -r $resourceType -f - 2>&1 # Should fail because second input has no match $LASTEXITCODE | Should -Not -Be 0 @@ -312,7 +312,7 @@ Describe 'Windows Update Get operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $out = $json | dsc resource get -r $resourceType 2>&1 + $out = $json | dsc resource get -r $resourceType -f - 2>&1 $LASTEXITCODE | Should -Be 0 $getResult = $out | ConvertFrom-Json @@ -334,7 +334,7 @@ Describe 'Windows Update Get operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $out = $json | dsc resource get -r $resourceType 2>&1 + $out = $json | dsc resource get -r $resourceType -f - 2>&1 $LASTEXITCODE | Should -Be 0 $getResult = $out | ConvertFrom-Json @@ -356,7 +356,7 @@ Describe 'Windows Update Get operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $out = $json | dsc resource get -r $resourceType 2>&1 + $out = $json | dsc resource get -r $resourceType -f - 2>&1 $LASTEXITCODE | Should -Be 0 $getResult = $out | ConvertFrom-Json @@ -374,7 +374,7 @@ Describe 'Windows Update Get operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $out = $json | dsc resource get -r $resourceType 2>&1 + $out = $json | dsc resource get -r $resourceType -f - 2>&1 $LASTEXITCODE | Should -Be 0 $result = $out | ConvertFrom-Json @@ -396,7 +396,7 @@ Describe 'Windows Update Get operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $out = $json | dsc resource get -r $resourceType 2>&1 + $out = $json | dsc resource get -r $resourceType -f - 2>&1 $LASTEXITCODE | Should -Be 0 $getResult = $out | ConvertFrom-Json @@ -424,7 +424,7 @@ Describe 'Windows Update Get operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $stderr = $json | dsc resource get -r $resourceType 2>&1 + $stderr = $json | dsc resource get -r $resourceType -f - 2>&1 # If multiple updates match isInstalled=true, it should error $installedCount = ($exportOut.updates | Where-Object { $_.isInstalled -eq $true }).Count @@ -460,7 +460,7 @@ Describe 'Windows Update Get operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $stderr = $json | dsc resource get -r $resourceType 2>&1 + $stderr = $json | dsc resource get -r $resourceType -f - 2>&1 # This may or may not fail depending on uniqueness if ($LASTEXITCODE -ne 0) { diff --git a/resources/WindowsUpdate/tests/windowsupdate_set.tests.ps1 b/resources/WindowsUpdate/tests/windowsupdate_set.tests.ps1 index 64266de58..a452d0210 100644 --- a/resources/WindowsUpdate/tests/windowsupdate_set.tests.ps1 +++ b/resources/WindowsUpdate/tests/windowsupdate_set.tests.ps1 @@ -17,7 +17,7 @@ Describe 'Windows Update Set operation tests' { Context 'Set operation' -Skip:(!$isAdmin -or !$IsWindows) { It 'should match when both title and id are correct' { # Get an actual installed update with both title and id - $exportOut = '{"updates": [{"isInstalled": true}]}' | dsc resource export -r $resourceType 2>&1 + $exportOut = '{"updates": [{"isInstalled": true}]}' | dsc resource export -r $resourceType -f - 2>&1 if ($LASTEXITCODE -eq 0) { $result = $exportOut | ConvertFrom-Json @@ -32,7 +32,7 @@ Describe 'Windows Update Set operation tests' { ) } | ConvertTo-Json -Depth 10 -Compress # Try to set (should detect already installed) - $out = $json | dsc resource set -r $resourceType 2>&1 + $out = $json | dsc resource set -r $resourceType -f - 2>&1 if ($LASTEXITCODE -eq 0) { $result = $out | ConvertFrom-Json @@ -50,7 +50,7 @@ Describe 'Windows Update Set operation tests' { It 'should fail when title matches but id does not' { # Get an actual update - $exportOut = '{"updates": []}' | dsc resource export -r $resourceType 2>&1 + $exportOut = '{"updates": []}' | dsc resource export -r $resourceType -f - 2>&1 if ($LASTEXITCODE -eq 0) { $result = $exportOut | ConvertFrom-Json @@ -64,7 +64,7 @@ Describe 'Windows Update Set operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $out = $json | dsc resource set -r $resourceType 2>&1 + $out = $json | dsc resource set -r $resourceType -f - 2>&1 # Should fail because id doesn't match $LASTEXITCODE | Should -Not -Be 0 @@ -78,7 +78,7 @@ Describe 'Windows Update Set operation tests' { It 'should fail when id matches but title does not' { # Get an actual update - $exportOut = '{"updates": []}' | dsc resource export -r $resourceType 2>&1 + $exportOut = '{"updates": []}' | dsc resource export -r $resourceType -f - 2>&1 if ($LASTEXITCODE -eq 0) { $result = $exportOut | ConvertFrom-Json @@ -92,7 +92,7 @@ Describe 'Windows Update Set operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $out = $json | dsc resource set -r $resourceType 2>&1 + $out = $json | dsc resource set -r $resourceType -f - 2>&1 # Should fail because title doesn't match $LASTEXITCODE | Should -Not -Be 0 @@ -106,7 +106,7 @@ Describe 'Windows Update Set operation tests' { It 'should verify all inputs have matches before installing' { # Get an actual update - $exportOut = '{"updates": []}' | dsc resource export -r $resourceType 2>&1 + $exportOut = '{"updates": []}' | dsc resource export -r $resourceType -f - 2>&1 if ($LASTEXITCODE -eq 0) { $result = $exportOut | ConvertFrom-Json @@ -124,7 +124,7 @@ Describe 'Windows Update Set operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $stderr = $json | dsc resource set -r $resourceType 2>&1 + $stderr = $json | dsc resource set -r $resourceType -f - 2>&1 # Should fail before attempting any installation $LASTEXITCODE | Should -Not -Be 0 @@ -142,7 +142,7 @@ Describe 'Windows Update Set operation tests' { It 'should process multiple valid input objects' { # Get an actual update - $exportOut = '{"updates": [{"isInstalled": true}]}' | dsc resource export -r $resourceType 2>&1 + $exportOut = '{"updates": [{"isInstalled": true}]}' | dsc resource export -r $resourceType -f - 2>&1 if ($LASTEXITCODE -eq 0) { $result = $exportOut | ConvertFrom-Json @@ -160,7 +160,7 @@ Describe 'Windows Update Set operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $out = $json | dsc resource set -r $resourceType 2>&1 + $out = $json | dsc resource set -r $resourceType -f - 2>&1 if ($LASTEXITCODE -eq 0) { $setResult = $out | ConvertFrom-Json @@ -175,7 +175,7 @@ Describe 'Windows Update Set operation tests' { It 'should apply logical AND for all criteria in each input' { # Get an actual update - $exportOut = '{"updates": [{"isInstalled": true}]}' | dsc resource export -r $resourceType 2>&1 + $exportOut = '{"updates": [{"isInstalled": true}]}' | dsc resource export -r $resourceType -f - 2>&1 if ($LASTEXITCODE -eq 0) { $result = $exportOut | ConvertFrom-Json @@ -192,7 +192,7 @@ Describe 'Windows Update Set operation tests' { } ) } | ConvertTo-Json -Depth 10 -Compress - $out = $json | dsc resource set -r $resourceType 2>&1 + $out = $json | dsc resource set -r $resourceType -f - 2>&1 if ($LASTEXITCODE -eq 0) { $setResult = $out | ConvertFrom-Json