DSCv3ResourceTestBase.cs (7679B)
1 // ----------------------------------------------------------------------------- 2 // <copyright file="DSCv3ResourceTestBase.cs" company="Microsoft Corporation"> 3 // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 4 // </copyright> 5 // ----------------------------------------------------------------------------- 6 7 namespace AppInstallerCLIE2ETests 8 { 9 using System; 10 using System.Collections.Generic; 11 using System.IO; 12 using System.Text.Json; 13 using System.Text.Json.Serialization; 14 using AppInstallerCLIE2ETests.Helpers; 15 using NUnit.Framework; 16 17 /// <summary> 18 /// Provides common functionality for DSC v3 resource tests. 19 /// </summary> 20 public class DSCv3ResourceTestBase 21 { 22 /// <summary> 23 /// The string for the `get` function. 24 /// </summary> 25 public const string GetFunction = "get"; 26 27 /// <summary> 28 /// The string for the `test` function. 29 /// </summary> 30 public const string TestFunction = "test"; 31 32 /// <summary> 33 /// The string for the `set` function. 34 /// </summary> 35 public const string SetFunction = "set"; 36 37 /// <summary> 38 /// The string for the `export` function. 39 /// </summary> 40 public const string ExportFunction = "export"; 41 42 /// <summary> 43 /// The string for the `_exist` property name. 44 /// </summary> 45 public const string ExistPropertyName = "_exist"; 46 47 /// <summary> 48 /// The string for the `_inDesiredState` property name. 49 /// </summary> 50 public const string InDesiredStatePropertyName = "_inDesiredState"; 51 52 /// <summary> 53 /// Write the resource manifests out to the WindowsApps alias directory. 54 /// </summary> 55 public static void EnsureTestResourcePresence() 56 { 57 string outputDirectory = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft\\WindowsApps"); 58 Assert.IsNotEmpty(outputDirectory); 59 60 var result = TestCommon.RunAICLICommand($"dscv3", $"--manifest -o {outputDirectory}"); 61 Assert.AreEqual(0, result.ExitCode); 62 } 63 64 /// <summary> 65 /// Runs a DSC v3 resource command. 66 /// </summary> 67 /// <param name="resource">The resource to target.</param> 68 /// <param name="function">The resource function to run.</param> 69 /// <param name="input">Input for the function; supports null, direct string, or JSON serialization of complex objects.</param> 70 /// <param name="timeOut">The maximum time to wait in milliseconds.</param> 71 /// <param name="throwOnTimeout">Whether to throw on a timeout or simply return the incomplete result.</param> 72 /// <returns>A RunCommandResult containing the process exit code and output and error streams.</returns> 73 protected static TestCommon.RunCommandResult RunDSCv3Command(string resource, string function, object input, int timeOut = 60000, bool throwOnTimeout = true) 74 { 75 return TestCommon.RunAICLICommand($"dscv3 {resource}", $"--{function}", ConvertToJSON(input), timeOut, throwOnTimeout); 76 } 77 78 /// <summary> 79 /// Asserts that a RunCommandResult contains a success for a DSC v3 resource command run. 80 /// </summary> 81 /// <param name="result">The result of a DSC v3 resource command run.</param> 82 protected static void AssertSuccessfulResourceRun(ref TestCommon.RunCommandResult result) 83 { 84 Assert.AreEqual(0, result.ExitCode); 85 Assert.IsNotEmpty(result.StdOut); 86 } 87 88 /// <summary> 89 /// Gets the output as lines. 90 /// </summary> 91 /// <param name="output">The output stream from a DSC v3 resource command.</param> 92 /// <returns>The lines of the output.</returns> 93 protected static string[] GetOutputLines(string output) 94 { 95 return output.TrimEnd().Split(Environment.NewLine); 96 } 97 98 /// <summary> 99 /// Asserts that the output is a single line and deserializes that line as JSON. 100 /// </summary> 101 /// <typeparam name="T">The type to deserialize from JSON.</typeparam> 102 /// <param name="output">The output stream from a DSC v3 resource command.</param> 103 /// <returns>The object as deserialized.</returns> 104 protected static T GetSingleOutputLineAs<T>(string output) 105 { 106 string[] lines = GetOutputLines(output); 107 Assert.AreEqual(1, lines.Length); 108 109 return JsonSerializer.Deserialize<T>(lines[0], GetDefaultJsonOptions()); 110 } 111 112 /// <summary> 113 /// Asserts that the output is two lines and deserializes them as a JSON object and JSON string array. 114 /// </summary> 115 /// <typeparam name="T">The type to deserialize from JSON.</typeparam> 116 /// <param name="output">The output stream from a DSC v3 resource command.</param> 117 /// <returns>The object as deserialized and the contents of the string array.</returns> 118 protected static (T, List<string>) GetSingleOutputLineAndDiffAs<T>(string output) 119 { 120 string[] lines = GetOutputLines(output); 121 Assert.AreEqual(2, lines.Length); 122 123 var options = GetDefaultJsonOptions(); 124 return (JsonSerializer.Deserialize<T>(lines[0], options), JsonSerializer.Deserialize<List<string>>(lines[1], options)); 125 } 126 127 /// <summary> 128 /// Deserializes all lines as JSON objects. 129 /// </summary> 130 /// <typeparam name="T">The type to deserialize from JSON.</typeparam> 131 /// <param name="output">The output stream from a DSC v3 resource command.</param> 132 /// <returns>A List of objects as deserialized.</returns> 133 protected static List<T> GetOutputLinesAs<T>(string output) 134 { 135 List<T> result = new List<T>(); 136 string[] lines = GetOutputLines(output); 137 var options = GetDefaultJsonOptions(); 138 139 foreach (string line in lines) 140 { 141 result.Add(JsonSerializer.Deserialize<T>(line, options)); 142 } 143 144 return result; 145 } 146 147 /// <summary> 148 /// Requires that the diff from a resource command contain the same set of strings as expected. 149 /// </summary> 150 /// <param name="diff">The diff from a resource command.</param> 151 /// <param name="expected">The expected strings.</param> 152 protected static void AssertDiffState(List<string> diff, IList<string> expected) 153 { 154 Assert.IsNotNull(diff); 155 Assert.AreEqual(expected.Count, diff.Count); 156 157 foreach (string item in expected) 158 { 159 Assert.Contains(item, diff); 160 } 161 } 162 163 private static JsonSerializerOptions GetDefaultJsonOptions() 164 { 165 return new JsonSerializerOptions() 166 { 167 DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, 168 PropertyNamingPolicy = JsonNamingPolicy.CamelCase, 169 Converters = 170 { 171 new JsonStringEnumConverter(), 172 }, 173 }; 174 } 175 176 private static string ConvertToJSON(object value) => value switch 177 { 178 string s => s, 179 null => null, 180 _ => JsonSerializer.Serialize(value, GetDefaultJsonOptions()), 181 }; 182 } 183 }