diff --git a/src/Microsoft.Dism.Tests/AddCapabilityAsyncTest.cs b/src/Microsoft.Dism.Tests/AddCapabilityAsyncTest.cs new file mode 100644 index 0000000..af01c74 --- /dev/null +++ b/src/Microsoft.Dism.Tests/AddCapabilityAsyncTest.cs @@ -0,0 +1,57 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. + +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class AddCapabilityAsyncTest : DismTestBase + { + public AddCapabilityAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + [Fact] + public async Task AddCapabilityAsync_ThrowsDismException() + { + using DismSession session = DismApi.OpenOnlineSession(); + + await Should.ThrowAsync( + () => DismApi.AddCapabilityAsync(session, "NonExistent.Capability~~~~0.0.1.0", false, null, cancellationToken: TestContext.Current.CancellationToken)); + } + + [Fact] + public async Task AddCapabilityAsync_WithCancelledToken_ThrowsOperationCanceledException() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(100)); + + Exception? ex = await Record.ExceptionAsync( + () => DismApi.AddCapabilityAsync(session, "NonExistent.Capability~~~~0.0.1.0", false, null, cancellationToken: cts.Token)); + + ex.ShouldNotBeNull(); + ex.ShouldBeAssignableTo(); + } + + [Fact] + public async Task AddCapabilityAsync_ReportsProgress() + { + using DismSession session = DismApi.OpenOnlineSession(); + var progress = new SynchronousProgress(_ => { }); + + try + { + await DismApi.AddCapabilityAsync(session, "NonExistent.Capability~~~~0.0.1.0", false, null, progress: progress, cancellationToken: TestContext.Current.CancellationToken); + } + catch (DismException) + { + } + } + } +} diff --git a/src/Microsoft.Dism.Tests/AddPackageAsyncTest.cs b/src/Microsoft.Dism.Tests/AddPackageAsyncTest.cs new file mode 100644 index 0000000..efd6d39 --- /dev/null +++ b/src/Microsoft.Dism.Tests/AddPackageAsyncTest.cs @@ -0,0 +1,57 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. + +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class AddPackageAsyncTest : DismTestBase + { + public AddPackageAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + [Fact] + public async Task AddPackageAsync_ThrowsDismException() + { + using DismSession session = DismApi.OpenOnlineSession(); + + await Should.ThrowAsync( + () => DismApi.AddPackageAsync(session, "nonexistent.cab", false, false, cancellationToken: TestContext.Current.CancellationToken)); + } + + [Fact] + public async Task AddPackageAsync_WithCancelledToken_ThrowsOperationCanceledException() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(100)); + + Exception? ex = await Record.ExceptionAsync( + () => DismApi.AddPackageAsync(session, "nonexistent.cab", false, false, cancellationToken: cts.Token)); + + ex.ShouldNotBeNull(); + ex.ShouldBeAssignableTo(); + } + + [Fact] + public async Task AddPackageAsync_ReportsProgress() + { + using DismSession session = DismApi.OpenOnlineSession(); + var progress = new SynchronousProgress(_ => { }); + + try + { + await DismApi.AddPackageAsync(session, "nonexistent.cab", false, false, progress: progress, cancellationToken: TestContext.Current.CancellationToken); + } + catch (DismException) + { + } + } + } +} diff --git a/src/Microsoft.Dism.Tests/CheckImageHealthAsyncTest.cs b/src/Microsoft.Dism.Tests/CheckImageHealthAsyncTest.cs new file mode 100644 index 0000000..bdb6a0e --- /dev/null +++ b/src/Microsoft.Dism.Tests/CheckImageHealthAsyncTest.cs @@ -0,0 +1,59 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. + +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class CheckImageHealthAsyncTest : DismTestBase + { + public CheckImageHealthAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + [Fact] + public async Task CheckImageHealthAsync_CompletesSuccessfully() + { + using DismSession session = DismApi.OpenOnlineSession(); + + DismImageHealthState result = await DismApi.CheckImageHealthAsync(session, scanImage: false, cancellationToken: TestContext.Current.CancellationToken); + + result.ShouldBe(DismImageHealthState.Healthy); + } + + [Fact] + public async Task CheckImageHealthAsync_WithCancelledToken_ThrowsOperationCanceledException() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(100)); + + await Should.ThrowAsync( + () => DismApi.CheckImageHealthAsync(session, scanImage: true, cancellationToken: cts.Token)); + } + + [Fact] + public async Task CheckImageHealthAsync_ReportsProgress() + { + using DismSession session = DismApi.OpenOnlineSession(); + bool progressReported = false; + var progress = new SynchronousProgress(_ => progressReported = true); + using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(1)); + + try + { + await DismApi.CheckImageHealthAsync(session, scanImage: true, progress: progress, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + } + + progressReported.ShouldBeTrue(); + } + } +} diff --git a/src/Microsoft.Dism.Tests/CommitImageAsyncTest.cs b/src/Microsoft.Dism.Tests/CommitImageAsyncTest.cs new file mode 100644 index 0000000..c963499 --- /dev/null +++ b/src/Microsoft.Dism.Tests/CommitImageAsyncTest.cs @@ -0,0 +1,55 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. + +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class CommitImageAsyncTest : DismInstallWimTestBase + { + public CommitImageAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + [Fact] + public async Task CommitImageAsync_CompletesSuccessfully() + { + await DismApi.CommitImageAsync(Session, discardChanges: true, cancellationToken: TestContext.Current.CancellationToken); + } + + [Fact] + public async Task CommitImageAsync_WithCancelledToken_ThrowsOperationCanceledException() + { + using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(100)); + + Exception? ex = await Record.ExceptionAsync( + () => DismApi.CommitImageAsync(Session, discardChanges: true, cancellationToken: cts.Token)); + + // The commit with discard may complete before cancellation fires + if (ex != null) + { + ex.ShouldBeAssignableTo(); + } + } + + [Fact] + public async Task CommitImageAsync_ReportsProgress() + { + var progress = new SynchronousProgress(_ => { }); + + try + { + await DismApi.CommitImageAsync(Session, discardChanges: true, progress: progress, cancellationToken: TestContext.Current.CancellationToken); + } + catch (OperationCanceledException) + { + } + } + } +} diff --git a/src/Microsoft.Dism.Tests/DisableFeatureAsyncTest.cs b/src/Microsoft.Dism.Tests/DisableFeatureAsyncTest.cs new file mode 100644 index 0000000..56ae980 --- /dev/null +++ b/src/Microsoft.Dism.Tests/DisableFeatureAsyncTest.cs @@ -0,0 +1,57 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. + +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class DisableFeatureAsyncTest : DismTestBase + { + public DisableFeatureAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + [Fact] + public async Task DisableFeatureAsync_ThrowsDismException() + { + using DismSession session = DismApi.OpenOnlineSession(); + + await Should.ThrowAsync( + () => DismApi.DisableFeatureAsync(session, "NonExistentFeature", "NonExistentPackage", false, cancellationToken: TestContext.Current.CancellationToken)); + } + + [Fact] + public async Task DisableFeatureAsync_WithCancelledToken_ThrowsOperationCanceledException() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(100)); + + Exception? ex = await Record.ExceptionAsync( + () => DismApi.DisableFeatureAsync(session, "NonExistentFeature", "NonExistentPackage", false, cancellationToken: cts.Token)); + + ex.ShouldNotBeNull(); + ex.ShouldBeAssignableTo(); + } + + [Fact] + public async Task DisableFeatureAsync_ReportsProgress() + { + using DismSession session = DismApi.OpenOnlineSession(); + var progress = new SynchronousProgress(_ => { }); + + try + { + await DismApi.DisableFeatureAsync(session, "NonExistentFeature", "NonExistentPackage", false, progress: progress, cancellationToken: TestContext.Current.CancellationToken); + } + catch (DismException) + { + } + } + } +} diff --git a/src/Microsoft.Dism.Tests/EnableFeatureAsyncTest.cs b/src/Microsoft.Dism.Tests/EnableFeatureAsyncTest.cs new file mode 100644 index 0000000..7b15eca --- /dev/null +++ b/src/Microsoft.Dism.Tests/EnableFeatureAsyncTest.cs @@ -0,0 +1,131 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. + +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class EnableFeatureAsyncTest : DismTestBase + { + public EnableFeatureAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + [Fact] + public async Task EnableFeatureAsync_ThrowsDismException() + { + using DismSession session = DismApi.OpenOnlineSession(); + + await Should.ThrowAsync( + () => DismApi.EnableFeatureAsync(session, "NonExistentFeature", false, false, cancellationToken: TestContext.Current.CancellationToken)); + } + + [Fact] + public async Task EnableFeatureAsync_WithCancelledToken_ThrowsOperationCanceledException() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(100)); + + Exception? ex = await Record.ExceptionAsync( + () => DismApi.EnableFeatureAsync(session, "NonExistentFeature", false, false, cancellationToken: cts.Token)); + + ex.ShouldNotBeNull(); + ex.ShouldBeAssignableTo(); + } + + [Fact] + public async Task EnableFeatureAsync_ReportsProgress() + { + using DismSession session = DismApi.OpenOnlineSession(); + var progress = new SynchronousProgress(_ => { }); + + try + { + await DismApi.EnableFeatureAsync(session, "NonExistentFeature", false, false, progress: progress, cancellationToken: TestContext.Current.CancellationToken); + } + catch (DismException) + { + } + } + + [Fact] + public async Task EnableFeatureByPackageNameAsync_ThrowsDismException() + { + using DismSession session = DismApi.OpenOnlineSession(); + + await Should.ThrowAsync( + () => DismApi.EnableFeatureByPackageNameAsync(session, "NonExistentFeature", "NonExistentPackage", false, false, cancellationToken: TestContext.Current.CancellationToken)); + } + + [Fact] + public async Task EnableFeatureByPackageNameAsync_WithCancelledToken_ThrowsOperationCanceledException() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(100)); + + Exception? ex = await Record.ExceptionAsync( + () => DismApi.EnableFeatureByPackageNameAsync(session, "NonExistentFeature", "NonExistentPackage", false, false, cancellationToken: cts.Token)); + + ex.ShouldNotBeNull(); + ex.ShouldBeAssignableTo(); + } + + [Fact] + public async Task EnableFeatureByPackageNameAsync_ReportsProgress() + { + using DismSession session = DismApi.OpenOnlineSession(); + var progress = new SynchronousProgress(_ => { }); + + try + { + await DismApi.EnableFeatureByPackageNameAsync(session, "NonExistentFeature", "NonExistentPackage", false, false, progress: progress, cancellationToken: TestContext.Current.CancellationToken); + } + catch (DismException) + { + } + } + + [Fact] + public async Task EnableFeatureByPackagePathAsync_ThrowsDismException() + { + using DismSession session = DismApi.OpenOnlineSession(); + + await Should.ThrowAsync( + () => DismApi.EnableFeatureByPackagePathAsync(session, "NonExistentFeature", "nonexistent.cab", false, false, cancellationToken: TestContext.Current.CancellationToken)); + } + + [Fact] + public async Task EnableFeatureByPackagePathAsync_WithCancelledToken_ThrowsOperationCanceledException() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(100)); + + Exception? ex = await Record.ExceptionAsync( + () => DismApi.EnableFeatureByPackagePathAsync(session, "NonExistentFeature", "nonexistent.cab", false, false, cancellationToken: cts.Token)); + + ex.ShouldNotBeNull(); + ex.ShouldBeAssignableTo(); + } + + [Fact] + public async Task EnableFeatureByPackagePathAsync_ReportsProgress() + { + using DismSession session = DismApi.OpenOnlineSession(); + var progress = new SynchronousProgress(_ => { }); + + try + { + await DismApi.EnableFeatureByPackagePathAsync(session, "NonExistentFeature", "nonexistent.cab", false, false, progress: progress, cancellationToken: TestContext.Current.CancellationToken); + } + catch (DismException) + { + } + } + } +} diff --git a/src/Microsoft.Dism.Tests/MountImageAsyncTest.cs b/src/Microsoft.Dism.Tests/MountImageAsyncTest.cs new file mode 100644 index 0000000..8c8e89d --- /dev/null +++ b/src/Microsoft.Dism.Tests/MountImageAsyncTest.cs @@ -0,0 +1,151 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. + +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class MountImageAsyncTest : DismTestBase + { + public MountImageAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + public override void Dispose() + { + try + { + DismApi.UnmountImage(MountPath.FullName, commitChanges: false); + } + catch + { + } + + base.Dispose(); + } + + [Fact] + public async Task MountImageAsync_ByIndex_CompletesSuccessfully() + { + await DismApi.MountImageAsync( + InstallWimPath.FullName, + MountPath.FullName, + imageIndex: 1, + readOnly: true, + options: DismMountImageOptions.None, + progress: null, + cancellationToken: TestContext.Current.CancellationToken); + } + + [Fact] + public async Task MountImageAsync_ByIndex_WithCancelledToken_ThrowsOperationCanceledException() + { + using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(100)); + + Exception? ex = await Record.ExceptionAsync( + () => DismApi.MountImageAsync( + InstallWimPath.FullName, + MountPath.FullName, + imageIndex: 1, + readOnly: true, + options: DismMountImageOptions.None, + progress: null, + cancellationToken: cts.Token)); + + // The mount may complete before cancellation, or be cancelled + if (ex != null) + { + ex.ShouldBeAssignableTo(); + } + } + + [Fact] + public async Task MountImageAsync_ByIndex_ReportsProgress() + { + bool progressReported = false; + var progress = new SynchronousProgress(_ => progressReported = true); + + try + { + await DismApi.MountImageAsync( + InstallWimPath.FullName, + MountPath.FullName, + imageIndex: 1, + readOnly: true, + options: DismMountImageOptions.None, + progress: progress, + cancellationToken: TestContext.Current.CancellationToken); + } + catch (OperationCanceledException) + { + } + + progressReported.ShouldBeTrue(); + } + + [Fact] + public async Task MountImageAsync_ByName_CompletesSuccessfully() + { + await DismApi.MountImageAsync( + InstallWimPath.FullName, + MountPath.FullName, + imageName: "Test Image 1", + readOnly: true, + options: DismMountImageOptions.None, + progress: null, + cancellationToken: TestContext.Current.CancellationToken); + } + + [Fact] + public async Task MountImageAsync_ByName_WithCancelledToken_ThrowsOperationCanceledException() + { + using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(100)); + + Exception? ex = await Record.ExceptionAsync( + () => DismApi.MountImageAsync( + InstallWimPath.FullName, + MountPath.FullName, + imageName: "Test Image 1", + readOnly: true, + options: DismMountImageOptions.None, + progress: null, + cancellationToken: cts.Token)); + + // The mount may complete before cancellation, or be cancelled + if (ex != null) + { + ex.ShouldBeAssignableTo(); + } + } + + [Fact] + public async Task MountImageAsync_ByName_ReportsProgress() + { + bool progressReported = false; + var progress = new SynchronousProgress(_ => progressReported = true); + + try + { + await DismApi.MountImageAsync( + InstallWimPath.FullName, + MountPath.FullName, + imageName: "Test Image 1", + readOnly: true, + options: DismMountImageOptions.None, + progress: progress, + cancellationToken: TestContext.Current.CancellationToken); + } + catch (OperationCanceledException) + { + } + + progressReported.ShouldBeTrue(); + } + } +} diff --git a/src/Microsoft.Dism.Tests/RemoveCapabilityAsyncTest.cs b/src/Microsoft.Dism.Tests/RemoveCapabilityAsyncTest.cs new file mode 100644 index 0000000..0c299c6 --- /dev/null +++ b/src/Microsoft.Dism.Tests/RemoveCapabilityAsyncTest.cs @@ -0,0 +1,57 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. + +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class RemoveCapabilityAsyncTest : DismTestBase + { + public RemoveCapabilityAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + [Fact] + public async Task RemoveCapabilityAsync_ThrowsDismException() + { + using DismSession session = DismApi.OpenOnlineSession(); + + await Should.ThrowAsync( + () => DismApi.RemoveCapabilityAsync(session, "NonExistent.Capability~~~~0.0.1.0", cancellationToken: TestContext.Current.CancellationToken)); + } + + [Fact] + public async Task RemoveCapabilityAsync_WithCancelledToken_ThrowsOperationCanceledException() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(100)); + + Exception? ex = await Record.ExceptionAsync( + () => DismApi.RemoveCapabilityAsync(session, "NonExistent.Capability~~~~0.0.1.0", cancellationToken: cts.Token)); + + ex.ShouldNotBeNull(); + ex.ShouldBeAssignableTo(); + } + + [Fact] + public async Task RemoveCapabilityAsync_ReportsProgress() + { + using DismSession session = DismApi.OpenOnlineSession(); + var progress = new SynchronousProgress(_ => { }); + + try + { + await DismApi.RemoveCapabilityAsync(session, "NonExistent.Capability~~~~0.0.1.0", progress: progress, cancellationToken: TestContext.Current.CancellationToken); + } + catch (DismException) + { + } + } + } +} diff --git a/src/Microsoft.Dism.Tests/RemovePackageAsyncTest.cs b/src/Microsoft.Dism.Tests/RemovePackageAsyncTest.cs new file mode 100644 index 0000000..f0242b4 --- /dev/null +++ b/src/Microsoft.Dism.Tests/RemovePackageAsyncTest.cs @@ -0,0 +1,94 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. + +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class RemovePackageAsyncTest : DismTestBase + { + public RemovePackageAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + [Fact] + public async Task RemovePackageByNameAsync_ThrowsDismException() + { + using DismSession session = DismApi.OpenOnlineSession(); + + await Should.ThrowAsync( + () => DismApi.RemovePackageByNameAsync(session, "NonExistentPackage", cancellationToken: TestContext.Current.CancellationToken)); + } + + [Fact] + public async Task RemovePackageByNameAsync_WithCancelledToken_ThrowsOperationCanceledException() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(100)); + + Exception? ex = await Record.ExceptionAsync( + () => DismApi.RemovePackageByNameAsync(session, "NonExistentPackage", cancellationToken: cts.Token)); + + ex.ShouldNotBeNull(); + ex.ShouldBeAssignableTo(); + } + + [Fact] + public async Task RemovePackageByNameAsync_ReportsProgress() + { + using DismSession session = DismApi.OpenOnlineSession(); + var progress = new SynchronousProgress(_ => { }); + + try + { + await DismApi.RemovePackageByNameAsync(session, "NonExistentPackage", progress: progress, cancellationToken: TestContext.Current.CancellationToken); + } + catch (DismException) + { + } + } + + [Fact] + public async Task RemovePackageByPathAsync_ThrowsDismException() + { + using DismSession session = DismApi.OpenOnlineSession(); + + await Should.ThrowAsync( + () => DismApi.RemovePackageByPathAsync(session, "nonexistent.cab", cancellationToken: TestContext.Current.CancellationToken)); + } + + [Fact] + public async Task RemovePackageByPathAsync_WithCancelledToken_ThrowsOperationCanceledException() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(100)); + + Exception? ex = await Record.ExceptionAsync( + () => DismApi.RemovePackageByPathAsync(session, "nonexistent.cab", cancellationToken: cts.Token)); + + ex.ShouldNotBeNull(); + ex.ShouldBeAssignableTo(); + } + + [Fact] + public async Task RemovePackageByPathAsync_ReportsProgress() + { + using DismSession session = DismApi.OpenOnlineSession(); + var progress = new SynchronousProgress(_ => { }); + + try + { + await DismApi.RemovePackageByPathAsync(session, "nonexistent.cab", progress: progress, cancellationToken: TestContext.Current.CancellationToken); + } + catch (DismException) + { + } + } + } +} diff --git a/src/Microsoft.Dism.Tests/RestoreImageHealthAsyncTest.cs b/src/Microsoft.Dism.Tests/RestoreImageHealthAsyncTest.cs new file mode 100644 index 0000000..3e70346 --- /dev/null +++ b/src/Microsoft.Dism.Tests/RestoreImageHealthAsyncTest.cs @@ -0,0 +1,57 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. + +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class RestoreImageHealthAsyncTest : DismTestBase + { + public RestoreImageHealthAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + [Fact] + public async Task RestoreImageHealthAsync_CompletesSuccessfully() + { + using DismSession session = DismApi.OpenOnlineSession(); + + await DismApi.RestoreImageHealthAsync(session, limitAccess: true, cancellationToken: TestContext.Current.CancellationToken); + } + + [Fact] + public async Task RestoreImageHealthAsync_WithCancelledToken_ThrowsOperationCanceledException() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(100)); + + await Should.ThrowAsync( + () => DismApi.RestoreImageHealthAsync(session, limitAccess: true, cancellationToken: cts.Token)); + } + + [Fact] + public async Task RestoreImageHealthAsync_ReportsProgress() + { + using DismSession session = DismApi.OpenOnlineSession(); + bool progressReported = false; + var progress = new SynchronousProgress(_ => progressReported = true); + using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(1)); + + try + { + await DismApi.RestoreImageHealthAsync(session, limitAccess: true, progress: progress, cancellationToken: cts.Token); + } + catch (OperationCanceledException) + { + } + + progressReported.ShouldBeTrue(); + } + } +} diff --git a/src/Microsoft.Dism.Tests/SetEditionAsyncTest.cs b/src/Microsoft.Dism.Tests/SetEditionAsyncTest.cs new file mode 100644 index 0000000..f812cae --- /dev/null +++ b/src/Microsoft.Dism.Tests/SetEditionAsyncTest.cs @@ -0,0 +1,94 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. + +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class SetEditionAsyncTest : DismTestBase + { + public SetEditionAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + [Fact] + public async Task SetEditionAsync_ThrowsDismException() + { + using DismSession session = DismApi.OpenOnlineSession(); + + await Should.ThrowAsync( + () => DismApi.SetEditionAsync(session, "NonExistentEdition", cancellationToken: TestContext.Current.CancellationToken)); + } + + [Fact] + public async Task SetEditionAsync_WithCancelledToken_ThrowsOperationCanceledException() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(100)); + + Exception? ex = await Record.ExceptionAsync( + () => DismApi.SetEditionAsync(session, "NonExistentEdition", cancellationToken: cts.Token)); + + ex.ShouldNotBeNull(); + ex.ShouldBeAssignableTo(); + } + + [Fact] + public async Task SetEditionAsync_ReportsProgress() + { + using DismSession session = DismApi.OpenOnlineSession(); + var progress = new SynchronousProgress(_ => { }); + + try + { + await DismApi.SetEditionAsync(session, "NonExistentEdition", progress: progress, cancellationToken: TestContext.Current.CancellationToken); + } + catch (DismException) + { + } + } + + [Fact] + public async Task SetEditionAndProductKeyAsync_ThrowsDismException() + { + using DismSession session = DismApi.OpenOnlineSession(); + + await Should.ThrowAsync( + () => DismApi.SetEditionAndProductKeyAsync(session, "NonExistentEdition", "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX", cancellationToken: TestContext.Current.CancellationToken)); + } + + [Fact] + public async Task SetEditionAndProductKeyAsync_WithCancelledToken_ThrowsOperationCanceledException() + { + using DismSession session = DismApi.OpenOnlineSession(); + using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(100)); + + Exception? ex = await Record.ExceptionAsync( + () => DismApi.SetEditionAndProductKeyAsync(session, "NonExistentEdition", "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX", cancellationToken: cts.Token)); + + ex.ShouldNotBeNull(); + ex.ShouldBeAssignableTo(); + } + + [Fact] + public async Task SetEditionAndProductKeyAsync_ReportsProgress() + { + using DismSession session = DismApi.OpenOnlineSession(); + var progress = new SynchronousProgress(_ => { }); + + try + { + await DismApi.SetEditionAndProductKeyAsync(session, "NonExistentEdition", "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX", progress: progress, cancellationToken: TestContext.Current.CancellationToken); + } + catch (DismException) + { + } + } + } +} diff --git a/src/Microsoft.Dism.Tests/SynchronousProgress.cs b/src/Microsoft.Dism.Tests/SynchronousProgress.cs new file mode 100644 index 0000000..8418fa4 --- /dev/null +++ b/src/Microsoft.Dism.Tests/SynchronousProgress.cs @@ -0,0 +1,17 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. + +using System; + +namespace Microsoft.Dism.Tests +{ + internal sealed class SynchronousProgress : IProgress + { + private readonly Action _handler; + + public SynchronousProgress(Action handler) => _handler = handler; + + public void Report(T value) => _handler(value); + } +} diff --git a/src/Microsoft.Dism.Tests/UnmountImageAsyncTest.cs b/src/Microsoft.Dism.Tests/UnmountImageAsyncTest.cs new file mode 100644 index 0000000..6ea517e --- /dev/null +++ b/src/Microsoft.Dism.Tests/UnmountImageAsyncTest.cs @@ -0,0 +1,75 @@ +// Copyright (c). All rights reserved. +// +// Licensed under the MIT license. + +using Shouldly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Dism.Tests +{ + public class UnmountImageAsyncTest : DismTestBase + { + public UnmountImageAsyncTest(TestWimTemplate template, ITestOutputHelper testOutput) + : base(template, testOutput) + { + } + + public override void Dispose() + { + try + { + DismApi.UnmountImage(MountPath.FullName, commitChanges: false); + } + catch + { + } + + base.Dispose(); + } + + [Fact] + public async Task UnmountImageAsync_CompletesSuccessfully() + { + DismApi.MountImage(InstallWimPath.FullName, MountPath.FullName, 1); + + await DismApi.UnmountImageAsync(MountPath.FullName, commitChanges: false, cancellationToken: TestContext.Current.CancellationToken); + } + + [Fact] + public async Task UnmountImageAsync_WithCancelledToken_ThrowsOperationCanceledException() + { + DismApi.MountImage(InstallWimPath.FullName, MountPath.FullName, 1); + using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(100)); + + Exception? ex = await Record.ExceptionAsync( + () => DismApi.UnmountImageAsync(MountPath.FullName, commitChanges: false, cancellationToken: cts.Token)); + + // The unmount may complete before cancellation fires, or be cancelled + if (ex != null) + { + ex.ShouldBeAssignableTo(); + } + } + + [Fact] + public async Task UnmountImageAsync_ReportsProgress() + { + DismApi.MountImage(InstallWimPath.FullName, MountPath.FullName, 1); + bool progressReported = false; + var progress = new SynchronousProgress(_ => progressReported = true); + + try + { + await DismApi.UnmountImageAsync(MountPath.FullName, commitChanges: false, progress: progress, cancellationToken: TestContext.Current.CancellationToken); + } + catch (OperationCanceledException) + { + } + + progressReported.ShouldBeTrue(); + } + } +}