diff options
30 files changed, 1032 insertions, 0 deletions
diff --git a/src/internal/SetBuildNumber/Directory.Packages.props.pp b/src/internal/SetBuildNumber/Directory.Packages.props.pp index 675907e5..48c07179 100644 --- a/src/internal/SetBuildNumber/Directory.Packages.props.pp +++ b/src/internal/SetBuildNumber/Directory.Packages.props.pp | |||
@@ -38,6 +38,7 @@ | |||
38 | <ItemGroup> | 38 | <ItemGroup> |
39 | <PackageVersion Include="System.Diagnostics.PerformanceCounter" Version="4.7.0" /> | 39 | <PackageVersion Include="System.Diagnostics.PerformanceCounter" Version="4.7.0" /> |
40 | <PackageVersion Include="System.DirectoryServices" Version="4.7.0" /> | 40 | <PackageVersion Include="System.DirectoryServices" Version="4.7.0" /> |
41 | <PackageVersion Include="System.DirectoryServices.AccountManagement" Version="4.7.0" /> | ||
41 | <PackageVersion Include="System.IO.Compression" Version="4.3.0" /> | 42 | <PackageVersion Include="System.IO.Compression" Version="4.3.0" /> |
42 | <!-- Warning: The version for System.IO.FileSystem.AccessControl must be kept in sync with WixToolset.Core.Native.nuspec --> | 43 | <!-- Warning: The version for System.IO.FileSystem.AccessControl must be kept in sync with WixToolset.Core.Native.nuspec --> |
43 | <PackageVersion Include="System.IO.FileSystem.AccessControl" Version="4.6.0" /> | 44 | <PackageVersion Include="System.IO.FileSystem.AccessControl" Version="4.6.0" /> |
diff --git a/src/test/burn/WixTestTools/UserVerifier.cs b/src/test/burn/WixTestTools/UserVerifier.cs new file mode 100644 index 00000000..b5218a79 --- /dev/null +++ b/src/test/burn/WixTestTools/UserVerifier.cs | |||
@@ -0,0 +1,348 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixTestTools | ||
4 | { | ||
5 | using System; | ||
6 | using System.Text; | ||
7 | using System.DirectoryServices; | ||
8 | using System.DirectoryServices.AccountManagement; | ||
9 | using System.Security.Principal; | ||
10 | using Xunit; | ||
11 | |||
12 | /// <summary> | ||
13 | /// Contains methods for User account verification | ||
14 | /// </summary> | ||
15 | public static class UserVerifier | ||
16 | { | ||
17 | public static class SIDStrings | ||
18 | { | ||
19 | // Built-In Local Groups | ||
20 | public static readonly string BUILTIN_ADMINISTRATORS = "S-1-5-32-544"; | ||
21 | public static readonly string BUILTIN_USERS = "S-1-5-32-545"; | ||
22 | public static readonly string BUILTIN_GUESTS = "S-1-5-32-546"; | ||
23 | public static readonly string BUILTIN_ACCOUNT_OPERATORS = "S-1-5-32-548"; | ||
24 | public static readonly string BUILTIN_SERVER_OPERATORS = "S-1-5-32-549"; | ||
25 | public static readonly string BUILTIN_PRINT_OPERATORS = "S-1-5-32-550"; | ||
26 | public static readonly string BUILTIN_BACKUP_OPERATORS = "S-1-5-32-551"; | ||
27 | public static readonly string BUILTIN_REPLICATOR = "S-1-5-32-552"; | ||
28 | |||
29 | // Special Groups | ||
30 | public static readonly string CREATOR_OWNER = "S-1-3-0"; | ||
31 | public static readonly string EVERYONE = "S-1-1-0"; | ||
32 | public static readonly string NT_AUTHORITY_NETWORK = "S-1-5-2"; | ||
33 | public static readonly string NT_AUTHORITY_INTERACTIVE = "S-1-5-4"; | ||
34 | public static readonly string NT_AUTHORITY_SYSTEM = "S-1-5-18"; | ||
35 | public static readonly string NT_AUTHORITY_Authenticated_Users = "S-1-5-11"; | ||
36 | public static readonly string NT_AUTHORITY_LOCAL_SERVICE = "S-1-5-19"; | ||
37 | public static readonly string NT_AUTHORITY_NETWORK_SERVICE = "S-1-5-20"; | ||
38 | } | ||
39 | |||
40 | /// <summary> | ||
41 | /// Create a local user on the machine | ||
42 | /// </summary> | ||
43 | /// <param name="userName"></param> | ||
44 | /// <param name="password"></param> | ||
45 | /// <remarks>Has to be run as an Admin</remarks> | ||
46 | public static void CreateLocalUser(string userName, string password) | ||
47 | { | ||
48 | DeleteLocalUser(userName); | ||
49 | UserPrincipal newUser = new UserPrincipal(new PrincipalContext(ContextType.Machine)); | ||
50 | newUser.SetPassword(password); | ||
51 | newUser.Name = userName; | ||
52 | newUser.Description = "New test User"; | ||
53 | newUser.UserCannotChangePassword = true; | ||
54 | newUser.PasswordNeverExpires = false; | ||
55 | newUser.Save(); | ||
56 | } | ||
57 | |||
58 | /// <summary> | ||
59 | /// Deletes a local user from the machine | ||
60 | /// </summary> | ||
61 | /// <param name="userName">user name to delete</param> | ||
62 | /// <remarks>Has to be run as an Admin</remarks> | ||
63 | public static void DeleteLocalUser(string userName) | ||
64 | { | ||
65 | UserPrincipal newUser = GetUser(String.Empty, userName); | ||
66 | if (null != newUser) | ||
67 | { | ||
68 | newUser.Delete(); | ||
69 | } | ||
70 | } | ||
71 | |||
72 | /// <summary> | ||
73 | /// Verifies that a user exisits or not | ||
74 | /// </summary> | ||
75 | /// <param name="domainName">domain name for the user, empty for local users</param> | ||
76 | /// <param name="userName">the user name</param> | ||
77 | public static bool UserExists(string domainName, string userName) | ||
78 | { | ||
79 | UserPrincipal user = GetUser(domainName, userName); | ||
80 | |||
81 | return null != user; | ||
82 | } | ||
83 | |||
84 | /// <summary> | ||
85 | /// Sets the user information for a given user | ||
86 | /// </summary> | ||
87 | /// <param name="domainName">domain name for the user, empty for local users</param> | ||
88 | /// <param name="userName">the user name</param> | ||
89 | /// <param name="passwordExpired">user is required to change the password on first login</param> | ||
90 | /// <param name="passwordNeverExpires">password never expires</param> | ||
91 | /// <param name="disabled">account is disabled</param> | ||
92 | public static void SetUserInformation(string domainName, string userName, bool passwordExpired, bool passwordNeverExpires, bool disabled) | ||
93 | { | ||
94 | UserPrincipal user = GetUser(domainName, userName); | ||
95 | |||
96 | Assert.False(null == user, String.Format("User '{0}' was not found under domain '{1}'.", userName, domainName)); | ||
97 | user.PasswordNeverExpires = passwordNeverExpires; | ||
98 | user.Enabled = !disabled; | ||
99 | if (passwordExpired) | ||
100 | { | ||
101 | user.ExpirePasswordNow(); | ||
102 | } | ||
103 | else | ||
104 | { | ||
105 | // extend the expiration date to a month | ||
106 | user.AccountExpirationDate = DateTime.Now.Add(new TimeSpan(30, 0, 0, 0, 0)); | ||
107 | } | ||
108 | user.Save(); | ||
109 | } | ||
110 | |||
111 | /// <summary> | ||
112 | /// Adds the specified user to the specified local group | ||
113 | /// </summary> | ||
114 | /// <param name="userName">User to add</param> | ||
115 | /// <param name="groupName">Group to add too</param> | ||
116 | public static void AddUserToGroup(string userName, string groupName) | ||
117 | { | ||
118 | DirectoryEntry localMachine; | ||
119 | DirectoryEntry localGroup; | ||
120 | |||
121 | localMachine = new DirectoryEntry("WinNT://" + Environment.MachineName.ToString()); | ||
122 | localGroup = localMachine.Children.Find(groupName, "group"); | ||
123 | Assert.False(null == localGroup, String.Format("Group '{0}' was not found.", groupName)); | ||
124 | DirectoryEntry user = FindActiveDirectoryUser(userName); | ||
125 | localGroup.Invoke("Add", new object[] { user.Path.ToString() }); | ||
126 | } | ||
127 | |||
128 | /// <summary> | ||
129 | /// Find the specified user in AD | ||
130 | /// </summary> | ||
131 | /// <param name="UserName">user name to lookup</param> | ||
132 | /// <returns>DirectoryEntry of the user</returns> | ||
133 | private static DirectoryEntry FindActiveDirectoryUser(string UserName) | ||
134 | { | ||
135 | var mLocalMachine = new DirectoryEntry("WinNT://" + Environment.MachineName.ToString()); | ||
136 | var mLocalEntries = mLocalMachine.Children; | ||
137 | |||
138 | var theUser = mLocalEntries.Find(UserName); | ||
139 | return theUser; | ||
140 | } | ||
141 | |||
142 | /// <summary> | ||
143 | /// Verifies the user information for a given user | ||
144 | /// </summary> | ||
145 | /// <param name="domainName">domain name for the user, empty for local users</param> | ||
146 | /// <param name="userName">the user name</param> | ||
147 | /// <param name="passwordExpired">user is required to change the password on first login</param> | ||
148 | /// <param name="passwordNeverExpires">password never expires</param> | ||
149 | /// <param name="disabled">account is disabled</param> | ||
150 | public static void VerifyUserInformation(string domainName, string userName, bool passwordExpired, bool passwordNeverExpires, bool disabled) | ||
151 | { | ||
152 | UserPrincipal user = GetUser(domainName, userName); | ||
153 | |||
154 | Assert.False(null == user, String.Format("User '{0}' was not found under domain '{1}'.", userName, domainName)); | ||
155 | |||
156 | Assert.True(passwordNeverExpires == user.PasswordNeverExpires, String.Format("Password Never Expires for user '{0}/{1}' is: '{2}', expected: '{3}'.", domainName, userName, user.PasswordNeverExpires, passwordNeverExpires)); | ||
157 | Assert.True(disabled != user.Enabled, String.Format("Disappled for user '{0}/{1}' is: '{2}', expected: '{3}'.", domainName, userName, !user.Enabled, disabled)); | ||
158 | |||
159 | DateTime expirationDate = user.AccountExpirationDate.GetValueOrDefault(); | ||
160 | bool accountExpired = expirationDate.ToLocalTime().CompareTo(DateTime.Now) <= 0; | ||
161 | Assert.True(passwordExpired == accountExpired, String.Format("Password Expired for user '{0}/{1}' is: '{2}', expected: '{3}'.", domainName, userName, accountExpired, passwordExpired)); | ||
162 | } | ||
163 | |||
164 | /// <summary> | ||
165 | /// Verify that a givin user is member of a local group | ||
166 | /// </summary> | ||
167 | /// <param name="domainName">domain name for the user, empty for local users</param> | ||
168 | /// <param name="userName">the user name</param> | ||
169 | /// <param name="groupNames">list of groups to check for membership</param> | ||
170 | public static void VerifyUserIsMemberOf(string domainName, string userName, params string[] groupNames) | ||
171 | { | ||
172 | IsUserMemberOf(domainName, userName, true, groupNames); | ||
173 | } | ||
174 | |||
175 | /// <summary> | ||
176 | /// Verify that a givin user is NOT member of a local group | ||
177 | /// </summary> | ||
178 | /// <param name="domainName">domain name for the user, empty for local users</param> | ||
179 | /// <param name="userName">the user name</param> | ||
180 | /// <param name="groupNames">list of groups to check for membership</param> | ||
181 | public static void VerifyUserIsNotMemberOf(string domainName, string userName, params string[] groupNames) | ||
182 | { | ||
183 | IsUserMemberOf(domainName, userName, false, groupNames); | ||
184 | } | ||
185 | |||
186 | /// <summary> | ||
187 | /// | ||
188 | /// </summary> | ||
189 | /// <param name="SID">SID to search for</param> | ||
190 | /// <returns>AccountName</returns> | ||
191 | public static string GetLocalUserNameFromSID(string sidString) | ||
192 | { | ||
193 | SecurityIdentifier sid = new SecurityIdentifier(sidString); | ||
194 | NTAccount account = (NTAccount)sid.Translate(typeof(NTAccount)); | ||
195 | return account.Value; | ||
196 | } | ||
197 | |||
198 | /// <summary> | ||
199 | /// Get the SID string for a given user name | ||
200 | /// </summary> | ||
201 | /// <param name="Domain"></param> | ||
202 | /// <param name="UserName"></param> | ||
203 | /// <returns>SID string</returns> | ||
204 | public static string GetSIDFromUserName(string Domain, string UserName) | ||
205 | { | ||
206 | string retVal = null; | ||
207 | string domain = Domain; | ||
208 | string name = UserName; | ||
209 | |||
210 | if (String.IsNullOrEmpty(domain)) | ||
211 | { | ||
212 | domain = System.Environment.MachineName; | ||
213 | } | ||
214 | |||
215 | try | ||
216 | { | ||
217 | DirectoryEntry de = new DirectoryEntry("WinNT://" + domain + "/" + name); | ||
218 | |||
219 | long iBigVal = 5; | ||
220 | byte[] bigArr = BitConverter.GetBytes(iBigVal); | ||
221 | System.DirectoryServices.PropertyCollection coll = de.Properties; | ||
222 | object obVal = coll["objectSid"].Value; | ||
223 | if (null != obVal) | ||
224 | { | ||
225 | retVal = ConvertByteToSidString((byte[])obVal); | ||
226 | } | ||
227 | } | ||
228 | catch (Exception ex) | ||
229 | { | ||
230 | retVal = String.Empty; | ||
231 | Console.Write(ex.Message); | ||
232 | } | ||
233 | |||
234 | return retVal; | ||
235 | } | ||
236 | |||
237 | /// <summary> | ||
238 | /// converts a byte array containing a SID into a string | ||
239 | /// </summary> | ||
240 | /// <param name="sidBytes"></param> | ||
241 | /// <returns>SID string</returns> | ||
242 | private static string ConvertByteToSidString(byte[] sidBytes) | ||
243 | { | ||
244 | short sSubAuthorityCount; | ||
245 | StringBuilder strSid = new StringBuilder(); | ||
246 | strSid.Append("S-"); | ||
247 | try | ||
248 | { | ||
249 | // Add SID revision. | ||
250 | strSid.Append(sidBytes[0].ToString()); | ||
251 | |||
252 | sSubAuthorityCount = Convert.ToInt16(sidBytes[1]); | ||
253 | |||
254 | // Next six bytes are SID authority value. | ||
255 | if (sidBytes[2] != 0 || sidBytes[3] != 0) | ||
256 | { | ||
257 | string strAuth = String.Format("0x{0:2x}{1:2x}{2:2x}{3:2x}{4:2x}{5:2x}", | ||
258 | (short)sidBytes[2], | ||
259 | (short)sidBytes[3], | ||
260 | (short)sidBytes[4], | ||
261 | (short)sidBytes[5], | ||
262 | (short)sidBytes[6], | ||
263 | (short)sidBytes[7]); | ||
264 | strSid.Append("-"); | ||
265 | strSid.Append(strAuth); | ||
266 | } | ||
267 | else | ||
268 | { | ||
269 | long iVal = (int)(sidBytes[7]) + | ||
270 | (int)(sidBytes[6] << 8) + | ||
271 | (int)(sidBytes[5] << 16) + | ||
272 | (int)(sidBytes[4] << 24); | ||
273 | strSid.Append("-"); | ||
274 | strSid.Append(iVal.ToString()); | ||
275 | } | ||
276 | |||
277 | // Get sub authority count... | ||
278 | int idxAuth = 0; | ||
279 | for (int i = 0; i < sSubAuthorityCount; i++) | ||
280 | { | ||
281 | idxAuth = 8 + i * 4; | ||
282 | uint iSubAuth = BitConverter.ToUInt32(sidBytes, idxAuth); | ||
283 | strSid.Append("-"); | ||
284 | strSid.Append(iSubAuth.ToString()); | ||
285 | } | ||
286 | } | ||
287 | catch (Exception ex) | ||
288 | { | ||
289 | Console.WriteLine(ex.Message); | ||
290 | return ""; | ||
291 | } | ||
292 | return strSid.ToString(); | ||
293 | } | ||
294 | |||
295 | /// <summary> | ||
296 | /// Verify that a given user is member of a local group | ||
297 | /// </summary> | ||
298 | /// <param name="domainName">domain name for the user, empty for local users</param> | ||
299 | /// <param name="userName">the user name</param> | ||
300 | /// <param name="shouldBeMember">whether the user is expected to be a member of the groups or not</param> | ||
301 | /// <param name="groupNames">list of groups to check for membership</param> | ||
302 | private static void IsUserMemberOf(string domainName, string userName, bool shouldBeMember, params string[] groupNames) | ||
303 | { | ||
304 | UserPrincipal user = GetUser(domainName, userName); | ||
305 | Assert.False(null == user, String.Format("User '{0}' was not found under domain '{1}'.", userName, domainName)); | ||
306 | |||
307 | bool missedAGroup = false; | ||
308 | string message = String.Empty; | ||
309 | foreach (string groupName in groupNames) | ||
310 | { | ||
311 | try | ||
312 | { | ||
313 | bool found = user.IsMemberOf(new PrincipalContext(ContextType.Machine), IdentityType.Name, groupName); | ||
314 | if (found != shouldBeMember) | ||
315 | { | ||
316 | missedAGroup = true; | ||
317 | message += String.Format("User '{0}/{1}' is {2} a member of local group '{3}'. \r\n", domainName, userName, found ? String.Empty : "NOT", groupName); | ||
318 | } | ||
319 | } | ||
320 | catch (System.DirectoryServices.AccountManagement.PrincipalOperationException) | ||
321 | { | ||
322 | missedAGroup = true; | ||
323 | message += String.Format("Local group '{0}' was not found. \r\n", groupName); | ||
324 | } | ||
325 | |||
326 | } | ||
327 | Assert.False(missedAGroup, message); | ||
328 | } | ||
329 | |||
330 | /// <summary> | ||
331 | /// Returns the UserPrincipal object for a given user | ||
332 | /// </summary> | ||
333 | /// <param name="domainName">Domain name to look under, if Empty the LocalMachine is assumned as the domain</param> | ||
334 | /// <param name="userName"></param> | ||
335 | /// <returns>UserPrinicipal Object for the user if found, or null other wise</returns> | ||
336 | private static UserPrincipal GetUser(string domainName, string userName) | ||
337 | { | ||
338 | if (String.IsNullOrEmpty(domainName)) | ||
339 | { | ||
340 | return UserPrincipal.FindByIdentity(new PrincipalContext(ContextType.Machine), IdentityType.Name, userName); | ||
341 | } | ||
342 | else | ||
343 | { | ||
344 | return UserPrincipal.Current;//.FindByIdentity(new PrincipalContext(ContextType.Domain,domainName), IdentityType.Name, userName); | ||
345 | } | ||
346 | } | ||
347 | } | ||
348 | } | ||
diff --git a/src/test/burn/WixTestTools/WixTestTools.csproj b/src/test/burn/WixTestTools/WixTestTools.csproj index 7b726560..49e14f25 100644 --- a/src/test/burn/WixTestTools/WixTestTools.csproj +++ b/src/test/burn/WixTestTools/WixTestTools.csproj | |||
@@ -9,6 +9,8 @@ | |||
9 | 9 | ||
10 | <ItemGroup> | 10 | <ItemGroup> |
11 | <PackageReference Include="Microsoft.Win32.Registry" /> | 11 | <PackageReference Include="Microsoft.Win32.Registry" /> |
12 | <PackageReference Include="System.DirectoryServices" /> | ||
13 | <PackageReference Include="System.DirectoryServices.AccountManagement" /> | ||
12 | <PackageReference Include="System.Security.Principal.Windows" /> | 14 | <PackageReference Include="System.Security.Principal.Windows" /> |
13 | <PackageReference Include="WixBuildTools.TestSupport" /> | 15 | <PackageReference Include="WixBuildTools.TestSupport" /> |
14 | <PackageReference Include="WixToolset.Data" /> | 16 | <PackageReference Include="WixToolset.Data" /> |
diff --git a/src/test/msi/Directory.Build.props b/src/test/msi/Directory.Build.props new file mode 100644 index 00000000..9e2a776f --- /dev/null +++ b/src/test/msi/Directory.Build.props | |||
@@ -0,0 +1,11 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
3 | <Project> | ||
4 | <PropertyGroup> | ||
5 | <SegmentName>IntegrationMsi</SegmentName> | ||
6 | <SignOutput>false</SignOutput> | ||
7 | </PropertyGroup> | ||
8 | |||
9 | <Import Project="..\..\Directory.Build.props" /> | ||
10 | <Import Project="Directory$(MSBuildProjectExtension).props" Condition=" Exists('Directory$(MSBuildProjectExtension).props') " /> | ||
11 | </Project> | ||
diff --git a/src/test/msi/Directory.Build.targets b/src/test/msi/Directory.Build.targets new file mode 100644 index 00000000..4e97b6ca --- /dev/null +++ b/src/test/msi/Directory.Build.targets | |||
@@ -0,0 +1,6 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
3 | <Project> | ||
4 | <Import Project="..\..\Directory.Build.targets" /> | ||
5 | <Import Project="Directory$(MSBuildProjectExtension).targets" Condition=" Exists('Directory$(MSBuildProjectExtension).targets') " /> | ||
6 | </Project> | ||
diff --git a/src/test/msi/Directory.wixproj.props b/src/test/msi/Directory.wixproj.props new file mode 100644 index 00000000..f824ff2a --- /dev/null +++ b/src/test/msi/Directory.wixproj.props | |||
@@ -0,0 +1,11 @@ | |||
1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
2 | <Project> | ||
3 | <PropertyGroup> | ||
4 | <TestGroupName Condition=" '$(TestGroupName)'=='' ">$([System.IO.Path]::GetFileName($([System.IO.Path]::GetDirectoryName($(MSBuildProjectDirectory)))))</TestGroupName> | ||
5 | <BaseIntermediateOutputPath>$(BaseOutputPath)obj\$(TestGroupName)\$(ProjectName)\</BaseIntermediateOutputPath> | ||
6 | <OutputPath>$(OutputPath)netcoreapp3.1\TestData\$(TestGroupName)\</OutputPath> | ||
7 | <DefaultCompressionLevel>None</DefaultCompressionLevel> | ||
8 | <CompilerAdditionalOptions>-wx</CompilerAdditionalOptions> | ||
9 | <SuppressValidation>true</SuppressValidation> | ||
10 | </PropertyGroup> | ||
11 | </Project> | ||
diff --git a/src/test/msi/Directory.wixproj.targets b/src/test/msi/Directory.wixproj.targets new file mode 100644 index 00000000..7dddb141 --- /dev/null +++ b/src/test/msi/Directory.wixproj.targets | |||
@@ -0,0 +1,13 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
3 | <Project> | ||
4 | <PropertyGroup> | ||
5 | <PackageName Condition=" '$(PackageName)' == '' ">$(MSBuildProjectName)</PackageName> | ||
6 | <DefineConstants>TestGroupName=$(TestGroupName);PackageName=$(PackageName);$(DefineConstants)</DefineConstants> | ||
7 | <DefineConstants Condition=" '$(CabPrefix)' != '' ">CabPrefix=$(CabPrefix);$(DefineConstants)</DefineConstants> | ||
8 | <DefineConstants Condition=" '$(ProductCode)' != '' ">ProductCode=$(ProductCode);$(DefineConstants)</DefineConstants> | ||
9 | <DefineConstants Condition=" '$(ProductComponentsRef)' == 'true' ">ProductComponents=1;$(DefineConstants)</DefineConstants> | ||
10 | <DefineConstants Condition=" '$(UpgradeCode)' != '' ">UpgradeCode=$(UpgradeCode);$(DefineConstants)</DefineConstants> | ||
11 | <DefineConstants Condition=" '$(Version)' != '' ">Version=$(Version);$(DefineConstants)</DefineConstants> | ||
12 | </PropertyGroup> | ||
13 | </Project> | ||
diff --git a/src/test/msi/MsiE2ETests.sln b/src/test/msi/MsiE2ETests.sln new file mode 100644 index 00000000..c8ba93ec --- /dev/null +++ b/src/test/msi/MsiE2ETests.sln | |||
@@ -0,0 +1,51 @@ | |||
1 |  | ||
2 | Microsoft Visual Studio Solution File, Format Version 12.00 | ||
3 | # Visual Studio Version 17 | ||
4 | VisualStudioVersion = 17.0.31919.166 | ||
5 | MinimumVisualStudioVersion = 10.0.40219.1 | ||
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixTestTools", "..\burn\WixTestTools\WixTestTools.csproj", "{3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}" | ||
7 | EndProject | ||
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolsetTest.MsiE2E", "WixToolsetTest.MsiE2E\WixToolsetTest.MsiE2E.csproj", "{68E1A5F8-0F44-4B38-8876-C101A2A019F2}" | ||
9 | EndProject | ||
10 | Global | ||
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
12 | Debug|Any CPU = Debug|Any CPU | ||
13 | Debug|x64 = Debug|x64 | ||
14 | Debug|x86 = Debug|x86 | ||
15 | Release|Any CPU = Release|Any CPU | ||
16 | Release|x64 = Release|x64 | ||
17 | Release|x86 = Release|x86 | ||
18 | EndGlobalSection | ||
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
20 | {3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
21 | {3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
22 | {3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}.Debug|x64.ActiveCfg = Debug|Any CPU | ||
23 | {3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}.Debug|x64.Build.0 = Debug|Any CPU | ||
24 | {3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}.Debug|x86.ActiveCfg = Debug|Any CPU | ||
25 | {3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}.Debug|x86.Build.0 = Debug|Any CPU | ||
26 | {3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
27 | {3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}.Release|Any CPU.Build.0 = Release|Any CPU | ||
28 | {3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}.Release|x64.ActiveCfg = Release|Any CPU | ||
29 | {3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}.Release|x64.Build.0 = Release|Any CPU | ||
30 | {3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}.Release|x86.ActiveCfg = Release|Any CPU | ||
31 | {3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}.Release|x86.Build.0 = Release|Any CPU | ||
32 | {68E1A5F8-0F44-4B38-8876-C101A2A019F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
33 | {68E1A5F8-0F44-4B38-8876-C101A2A019F2}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
34 | {68E1A5F8-0F44-4B38-8876-C101A2A019F2}.Debug|x64.ActiveCfg = Debug|Any CPU | ||
35 | {68E1A5F8-0F44-4B38-8876-C101A2A019F2}.Debug|x64.Build.0 = Debug|Any CPU | ||
36 | {68E1A5F8-0F44-4B38-8876-C101A2A019F2}.Debug|x86.ActiveCfg = Debug|Any CPU | ||
37 | {68E1A5F8-0F44-4B38-8876-C101A2A019F2}.Debug|x86.Build.0 = Debug|Any CPU | ||
38 | {68E1A5F8-0F44-4B38-8876-C101A2A019F2}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
39 | {68E1A5F8-0F44-4B38-8876-C101A2A019F2}.Release|Any CPU.Build.0 = Release|Any CPU | ||
40 | {68E1A5F8-0F44-4B38-8876-C101A2A019F2}.Release|x64.ActiveCfg = Release|Any CPU | ||
41 | {68E1A5F8-0F44-4B38-8876-C101A2A019F2}.Release|x64.Build.0 = Release|Any CPU | ||
42 | {68E1A5F8-0F44-4B38-8876-C101A2A019F2}.Release|x86.ActiveCfg = Release|Any CPU | ||
43 | {68E1A5F8-0F44-4B38-8876-C101A2A019F2}.Release|x86.Build.0 = Release|Any CPU | ||
44 | EndGlobalSection | ||
45 | GlobalSection(SolutionProperties) = preSolution | ||
46 | HideSolutionNode = FALSE | ||
47 | EndGlobalSection | ||
48 | GlobalSection(ExtensibilityGlobals) = postSolution | ||
49 | SolutionGuid = {4C9978E3-8548-451E-8BF5-03AD1D0280C2} | ||
50 | EndGlobalSection | ||
51 | EndGlobal | ||
diff --git a/src/test/msi/README.md b/src/test/msi/README.md new file mode 100644 index 00000000..2b4ff9a4 --- /dev/null +++ b/src/test/msi/README.md | |||
@@ -0,0 +1,29 @@ | |||
1 | # integration | ||
2 | |||
3 | This layer is for building installers, and then executing xunit tests that run them and verify that they worked. | ||
4 | |||
5 | ## Running tests | ||
6 | |||
7 | The main focus of these tests is to validate behavior in a real environment. | ||
8 | Depending on who you talk to, these are integration or system-level or end-to-end (E2E) tests. | ||
9 | They modify machine state so it's strongly recommended *not* to run these tests on your dev box. | ||
10 | They should be run on a VM instead, where you can easily roll back. | ||
11 | |||
12 | 1. Run build.cmd to build everything (the tests will not automatically run). | ||
13 | 1. Copy the build\IntegrationMsi\Debug\netcoreapp3.1 folder to your VM. | ||
14 | 1. Open an elevated command prompt and navigate to the netcoreapp3.1 folder. | ||
15 | 1. Run the runtests.cmd file to run the tests. | ||
16 | |||
17 | You can modify the runtests.cmd to run specific tests. | ||
18 | For example, the following line runs only the specified test: | ||
19 | |||
20 | > dotnet test --filter WixToolsetTest.BurnE2E.BasicFunctionalityTests.CanInstallAndUninstallSimpleBundle_x86_wixstdba WixToolsetTest.BurnE2E.dll | ||
21 | |||
22 | The VM must have: | ||
23 | 1. x64 .NET Core SDK of 3.1 or later (for the test runner) | ||
24 | |||
25 | ## Building with local changes | ||
26 | |||
27 | The current build process will poison your NuGet package cache, so you may have to run the following command to clear it: | ||
28 | |||
29 | > nuget locals all -clear \ No newline at end of file | ||
diff --git a/src/test/msi/TestData/Templates/CustomActionFail.exe b/src/test/msi/TestData/Templates/CustomActionFail.exe new file mode 100644 index 00000000..cceffe91 --- /dev/null +++ b/src/test/msi/TestData/Templates/CustomActionFail.exe | |||
Binary files differ | |||
diff --git a/src/test/msi/TestData/Templates/Product.wxs b/src/test/msi/TestData/Templates/Product.wxs new file mode 100644 index 00000000..c7604c1b --- /dev/null +++ b/src/test/msi/TestData/Templates/Product.wxs | |||
@@ -0,0 +1,47 @@ | |||
1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
2 | |||
3 | |||
4 | |||
5 | <?ifndef Version?> | ||
6 | <?define Version = 1.0.0.0?> | ||
7 | <?endif?> | ||
8 | |||
9 | <?ifndef ProductCode?> | ||
10 | <?define ProductCode = *?> | ||
11 | <?endif?> | ||
12 | |||
13 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
14 | <Package Name="~$(var.TestGroupName) - $(var.PackageName)" Language="1033" Version="$(var.Version)" Manufacturer="WixToolset" UpgradeCode="$(var.UpgradeCode)" Compressed="yes" ProductCode="$(var.ProductCode)"> | ||
15 | <MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." /> | ||
16 | <?ifndef CabPrefix?> | ||
17 | <MediaTemplate EmbedCab="yes" /> | ||
18 | <?else?> | ||
19 | <MediaTemplate CabinetTemplate="{0}$(var.CabPrefix).cab" /> | ||
20 | <?endif?> | ||
21 | |||
22 | <Feature Id="Complete" Level="1"> | ||
23 | <ComponentRef Id="FileComponent" /> | ||
24 | <?ifdef var.ProductComponents?> | ||
25 | <ComponentGroupRef Id="ProductComponents" /> | ||
26 | <?endif?> | ||
27 | </Feature> | ||
28 | </Package> | ||
29 | |||
30 | <Fragment> | ||
31 | <StandardDirectory Id="ProgramFiles6432Folder"> | ||
32 | <Directory Id="WixDir" Name="~Test WiX"> | ||
33 | <Directory Id="TestDir" Name="$(var.TestGroupName)"> | ||
34 | <Directory Id="INSTALLFOLDER" Name="$(var.PackageName)" /> | ||
35 | </Directory> | ||
36 | </Directory> | ||
37 | </StandardDirectory> | ||
38 | </Fragment> | ||
39 | |||
40 | <Fragment> | ||
41 | <Component Id="FileComponent" Guid="12345678-9ABC-DEF0-1234-567890000000" Directory="INSTALLFOLDER"> | ||
42 | <File Id="CAFile" Name="CustomActionFail.exe" Source="$(sys.SOURCEFILEDIR)\CustomActionFail.exe" /> | ||
43 | </Component> | ||
44 | |||
45 | <CustomAction Id="CaFail" FileRef="CAFile" Execute="immediate" Return="check" ExeCommand="" /> | ||
46 | </Fragment> | ||
47 | </Wix> | ||
diff --git a/src/test/msi/TestData/TestData.proj b/src/test/msi/TestData/TestData.proj new file mode 100644 index 00000000..9e130987 --- /dev/null +++ b/src/test/msi/TestData/TestData.proj | |||
@@ -0,0 +1,16 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
3 | |||
4 | <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
5 | <ItemGroup> | ||
6 | <TestDataProject Include="**\*.wixproj" /> | ||
7 | </ItemGroup> | ||
8 | |||
9 | <Target Name="Build"> | ||
10 | <MSBuild Projects="%(TestDataProject.Identity)" /> | ||
11 | </Target> | ||
12 | |||
13 | <Target Name="Restore"> | ||
14 | <MSBuild Projects="%(TestDataProject.Identity)" Targets="Restore" /> | ||
15 | </Target> | ||
16 | </Project> | ||
diff --git a/src/test/msi/TestData/UtilExtensionUserTests/ProductA/ProductA.wixproj b/src/test/msi/TestData/UtilExtensionUserTests/ProductA/ProductA.wixproj new file mode 100644 index 00000000..fbc6f292 --- /dev/null +++ b/src/test/msi/TestData/UtilExtensionUserTests/ProductA/ProductA.wixproj | |||
@@ -0,0 +1,13 @@ | |||
1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
2 | <Project Sdk="WixToolset.Sdk"> | ||
3 | <PropertyGroup> | ||
4 | <UpgradeCode>{1A1795A6-87C0-4A9A-ABD5-DF9BED697037}</UpgradeCode> | ||
5 | <ProductComponentsRef>true</ProductComponentsRef> | ||
6 | </PropertyGroup> | ||
7 | <ItemGroup> | ||
8 | <Compile Include="..\..\Templates\Product.wxs" Link="Product.wxs" /> | ||
9 | </ItemGroup> | ||
10 | <ItemGroup> | ||
11 | <PackageReference Include="WixToolset.Util.wixext" /> | ||
12 | </ItemGroup> | ||
13 | </Project> \ No newline at end of file | ||
diff --git a/src/test/msi/TestData/UtilExtensionUserTests/ProductA/product.wxs b/src/test/msi/TestData/UtilExtensionUserTests/ProductA/product.wxs new file mode 100644 index 00000000..a7bec54e --- /dev/null +++ b/src/test/msi/TestData/UtilExtensionUserTests/ProductA/product.wxs | |||
@@ -0,0 +1,35 @@ | |||
1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
2 | |||
3 | |||
4 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util"> | ||
5 | <Fragment> | ||
6 | <ComponentGroup Id="ProductComponents"> | ||
7 | <ComponentRef Id="Component1" /> | ||
8 | </ComponentGroup> | ||
9 | |||
10 | <Property Id="TEMPDOMAIN" Secure="yes" /> | ||
11 | <Property Id="TEMPUSERNAME" Secure="yes" /> | ||
12 | </Fragment> | ||
13 | |||
14 | <Fragment> | ||
15 | <util:Group Id="ADMIN" Name="Administrators" /> | ||
16 | <util:Group Id="POWER_USER" Name="Power Users" /> | ||
17 | |||
18 | <Component Id="Component1" Guid="00030829-0000-0000-C000-000000000046" Directory="INSTALLFOLDER"> | ||
19 | <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" /> | ||
20 | |||
21 | <util:User Id="TEST_USER1" Name="testName1" Password="test123!@#" PasswordExpired="yes"> | ||
22 | <util:GroupRef Id="ADMIN" /> | ||
23 | <util:GroupRef Id="POWER_USER" /> | ||
24 | </util:User> | ||
25 | |||
26 | <util:User Id="TEST_USER2" Name="testName2" Password="test123!@#" Disabled="yes" RemoveOnUninstall="no" PasswordNeverExpires="yes" UpdateIfExists="yes"> | ||
27 | <util:GroupRef Id="POWER_USER" /> | ||
28 | </util:User> | ||
29 | |||
30 | <util:User Id="TEST_USER3" Name="[TEMPUSERNAME]" Domain="[TEMPDOMAIN]" CreateUser="no"> | ||
31 | <util:GroupRef Id="POWER_USER" /> | ||
32 | </util:User> | ||
33 | </Component> | ||
34 | </Fragment> | ||
35 | </Wix> | ||
diff --git a/src/test/msi/TestData/UtilExtensionUserTests/ProductFail/ProductFail.wixproj b/src/test/msi/TestData/UtilExtensionUserTests/ProductFail/ProductFail.wixproj new file mode 100644 index 00000000..e2fe3aa8 --- /dev/null +++ b/src/test/msi/TestData/UtilExtensionUserTests/ProductFail/ProductFail.wixproj | |||
@@ -0,0 +1,13 @@ | |||
1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
2 | <Project Sdk="WixToolset.Sdk"> | ||
3 | <PropertyGroup> | ||
4 | <UpgradeCode>{91D27DAC-04C1-4160-914E-343676D36CAA}</UpgradeCode> | ||
5 | <ProductComponentsRef>true</ProductComponentsRef> | ||
6 | </PropertyGroup> | ||
7 | <ItemGroup> | ||
8 | <Compile Include="..\..\Templates\Product.wxs" Link="Product.wxs" /> | ||
9 | </ItemGroup> | ||
10 | <ItemGroup> | ||
11 | <PackageReference Include="WixToolset.Util.wixext" /> | ||
12 | </ItemGroup> | ||
13 | </Project> \ No newline at end of file | ||
diff --git a/src/test/msi/TestData/UtilExtensionUserTests/ProductFail/product_fail.wxs b/src/test/msi/TestData/UtilExtensionUserTests/ProductFail/product_fail.wxs new file mode 100644 index 00000000..c5da862c --- /dev/null +++ b/src/test/msi/TestData/UtilExtensionUserTests/ProductFail/product_fail.wxs | |||
@@ -0,0 +1,39 @@ | |||
1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
2 | |||
3 | |||
4 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util"> | ||
5 | <Fragment> | ||
6 | <ComponentGroup Id="ProductComponents"> | ||
7 | <ComponentRef Id="Component1" /> | ||
8 | </ComponentGroup> | ||
9 | |||
10 | <Property Id="TEMPDOMAIN" Secure="yes" /> | ||
11 | <Property Id="TEMPUSERNAME" Secure="yes" /> | ||
12 | |||
13 | <InstallExecuteSequence> | ||
14 | <Custom Action="CaFail" After="Wix4ConfigureUsers_X86" /> | ||
15 | </InstallExecuteSequence> | ||
16 | </Fragment> | ||
17 | |||
18 | <Fragment> | ||
19 | <util:Group Id="ADMIN" Name="Administrators" /> | ||
20 | <util:Group Id="POWER_USER" Name="Power Users" /> | ||
21 | |||
22 | <Component Id="Component1" Guid="00030829-0000-0000-C000-000000000046" Directory="INSTALLFOLDER"> | ||
23 | <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" /> | ||
24 | |||
25 | <util:User Id="TEST_USER1" Name="testName1" Password="test123!@#" PasswordExpired="yes"> | ||
26 | <util:GroupRef Id="ADMIN" /> | ||
27 | <util:GroupRef Id="POWER_USER" /> | ||
28 | </util:User> | ||
29 | |||
30 | <util:User Id="TEST_USER2" Name="testName2" Password="test123!@#" Disabled="yes" RemoveOnUninstall="no" PasswordNeverExpires="yes" UpdateIfExists="yes"> | ||
31 | <util:GroupRef Id="POWER_USER" /> | ||
32 | </util:User> | ||
33 | |||
34 | <util:User Id="TEST_USER3" Name="[TEMPUSERNAME]" Domain="[TEMPDOMAIN]" CreateUser="no"> | ||
35 | <util:GroupRef Id="POWER_USER" /> | ||
36 | </util:User> | ||
37 | </Component> | ||
38 | </Fragment> | ||
39 | </Wix> | ||
diff --git a/src/test/msi/TestData/UtilExtensionUserTests/ProductFailIfExists/FailIfExists.wxs b/src/test/msi/TestData/UtilExtensionUserTests/ProductFailIfExists/FailIfExists.wxs new file mode 100644 index 00000000..0da4f2b9 --- /dev/null +++ b/src/test/msi/TestData/UtilExtensionUserTests/ProductFailIfExists/FailIfExists.wxs | |||
@@ -0,0 +1,24 @@ | |||
1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
2 | |||
3 | |||
4 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util"> | ||
5 | <Fragment> | ||
6 | <ComponentGroup Id="ProductComponents"> | ||
7 | <ComponentRef Id="Component1" /> | ||
8 | </ComponentGroup> | ||
9 | </Fragment> | ||
10 | |||
11 | <Fragment> | ||
12 | <util:Group Id="ADMIN" Name="Administrators" /> | ||
13 | <util:Group Id="POWER_USER" Name="Power Users" /> | ||
14 | |||
15 | <Component Id="Component1" Guid="00030829-0000-0000-C000-000000000046" Directory="INSTALLFOLDER"> | ||
16 | <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" /> | ||
17 | |||
18 | <util:User Id="TEST_USER4" Name="existinguser" Password="test123!@#" LogonAsService="yes" FailIfExists="yes" RemoveOnUninstall="yes"> | ||
19 | <util:GroupRef Id="ADMIN" /> | ||
20 | <util:GroupRef Id="POWER_USER" /> | ||
21 | </util:User> | ||
22 | </Component> | ||
23 | </Fragment> | ||
24 | </Wix> | ||
diff --git a/src/test/msi/TestData/UtilExtensionUserTests/ProductFailIfExists/ProductFailIfExists.wixproj b/src/test/msi/TestData/UtilExtensionUserTests/ProductFailIfExists/ProductFailIfExists.wixproj new file mode 100644 index 00000000..9e1a836f --- /dev/null +++ b/src/test/msi/TestData/UtilExtensionUserTests/ProductFailIfExists/ProductFailIfExists.wixproj | |||
@@ -0,0 +1,13 @@ | |||
1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
2 | <Project Sdk="WixToolset.Sdk"> | ||
3 | <PropertyGroup> | ||
4 | <UpgradeCode>{BC803822-929E-47DA-AB3A-3A62EEEA2BFB}</UpgradeCode> | ||
5 | <ProductComponentsRef>true</ProductComponentsRef> | ||
6 | </PropertyGroup> | ||
7 | <ItemGroup> | ||
8 | <Compile Include="..\..\Templates\Product.wxs" Link="Product.wxs" /> | ||
9 | </ItemGroup> | ||
10 | <ItemGroup> | ||
11 | <PackageReference Include="WixToolset.Util.wixext" /> | ||
12 | </ItemGroup> | ||
13 | </Project> \ No newline at end of file | ||
diff --git a/src/test/msi/TestData/UtilExtensionUserTests/ProductNonVitalUserGroup/NonVitalUserGroup.wxs b/src/test/msi/TestData/UtilExtensionUserTests/ProductNonVitalUserGroup/NonVitalUserGroup.wxs new file mode 100644 index 00000000..461648ee --- /dev/null +++ b/src/test/msi/TestData/UtilExtensionUserTests/ProductNonVitalUserGroup/NonVitalUserGroup.wxs | |||
@@ -0,0 +1,22 @@ | |||
1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
2 | |||
3 | |||
4 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util"> | ||
5 | <Fragment> | ||
6 | <ComponentGroup Id="ProductComponents"> | ||
7 | <ComponentRef Id="Component1" /> | ||
8 | </ComponentGroup> | ||
9 | </Fragment> | ||
10 | |||
11 | <Fragment> | ||
12 | <util:Group Id="ShouldNotExist" Name="Should Not Exist" /> | ||
13 | |||
14 | <Component Id="Component1" Guid="00030829-0000-0000-C000-000000000046" Directory="INSTALLFOLDER"> | ||
15 | <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" /> | ||
16 | |||
17 | <util:User Id="CurrentUser" Name="[LogonUser]" Domain="[%USERDOMAIN]" RemoveOnUninstall="no" Vital="no"> | ||
18 | <util:GroupRef Id="ShouldNotExist" /> | ||
19 | </util:User> | ||
20 | </Component> | ||
21 | </Fragment> | ||
22 | </Wix> | ||
diff --git a/src/test/msi/TestData/UtilExtensionUserTests/ProductNonVitalUserGroup/ProductNonVitalUserGroup.wixproj b/src/test/msi/TestData/UtilExtensionUserTests/ProductNonVitalUserGroup/ProductNonVitalUserGroup.wixproj new file mode 100644 index 00000000..8734224d --- /dev/null +++ b/src/test/msi/TestData/UtilExtensionUserTests/ProductNonVitalUserGroup/ProductNonVitalUserGroup.wixproj | |||
@@ -0,0 +1,13 @@ | |||
1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
2 | <Project Sdk="WixToolset.Sdk"> | ||
3 | <PropertyGroup> | ||
4 | <UpgradeCode>{455C8D4F-6D59-405C-AD51-0ACC7FB91A26}</UpgradeCode> | ||
5 | <ProductComponentsRef>true</ProductComponentsRef> | ||
6 | </PropertyGroup> | ||
7 | <ItemGroup> | ||
8 | <Compile Include="..\..\Templates\Product.wxs" Link="Product.wxs" /> | ||
9 | </ItemGroup> | ||
10 | <ItemGroup> | ||
11 | <PackageReference Include="WixToolset.Util.wixext" /> | ||
12 | </ItemGroup> | ||
13 | </Project> \ No newline at end of file | ||
diff --git a/src/test/msi/TestData/UtilExtensionUserTests/ProductRestrictedDomain/ProductRestrictedDomain.wixproj b/src/test/msi/TestData/UtilExtensionUserTests/ProductRestrictedDomain/ProductRestrictedDomain.wixproj new file mode 100644 index 00000000..e4a01a3a --- /dev/null +++ b/src/test/msi/TestData/UtilExtensionUserTests/ProductRestrictedDomain/ProductRestrictedDomain.wixproj | |||
@@ -0,0 +1,13 @@ | |||
1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
2 | <Project Sdk="WixToolset.Sdk"> | ||
3 | <PropertyGroup> | ||
4 | <UpgradeCode>{50CF526C-A862-4327-9EA3-C96AAB6FABCE}</UpgradeCode> | ||
5 | <ProductComponentsRef>true</ProductComponentsRef> | ||
6 | </PropertyGroup> | ||
7 | <ItemGroup> | ||
8 | <Compile Include="..\..\Templates\Product.wxs" Link="Product.wxs" /> | ||
9 | </ItemGroup> | ||
10 | <ItemGroup> | ||
11 | <PackageReference Include="WixToolset.Util.wixext" /> | ||
12 | </ItemGroup> | ||
13 | </Project> \ No newline at end of file | ||
diff --git a/src/test/msi/TestData/UtilExtensionUserTests/ProductRestrictedDomain/RestrictedDomain.wxs b/src/test/msi/TestData/UtilExtensionUserTests/ProductRestrictedDomain/RestrictedDomain.wxs new file mode 100644 index 00000000..f200a06a --- /dev/null +++ b/src/test/msi/TestData/UtilExtensionUserTests/ProductRestrictedDomain/RestrictedDomain.wxs | |||
@@ -0,0 +1,20 @@ | |||
1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
2 | |||
3 | |||
4 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util"> | ||
5 | <Fragment> | ||
6 | <ComponentGroup Id="ProductComponents"> | ||
7 | <ComponentRef Id="Component1" /> | ||
8 | </ComponentGroup> | ||
9 | |||
10 | <Property Id="TEMPDOMAIN" Secure="yes" /> | ||
11 | </Fragment> | ||
12 | |||
13 | <Fragment> | ||
14 | <Component Id="Component1" Guid="00030829-0000-0000-C000-000000000046" Directory="INSTALLFOLDER"> | ||
15 | <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" /> | ||
16 | |||
17 | <util:User Id="TEST_USER_test" Name="testName1" Domain="[TEMPDOMAIN]" Password="test123!@#" PasswordExpired="no" /> | ||
18 | </Component> | ||
19 | </Fragment> | ||
20 | </Wix> | ||
diff --git a/src/test/msi/WixToolsetTest.MsiE2E/MsiE2EFixture.cs b/src/test/msi/WixToolsetTest.MsiE2E/MsiE2EFixture.cs new file mode 100644 index 00000000..a7646568 --- /dev/null +++ b/src/test/msi/WixToolsetTest.MsiE2E/MsiE2EFixture.cs | |||
@@ -0,0 +1,28 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolsetTest.MsiE2E | ||
4 | { | ||
5 | using System; | ||
6 | using System.Security.Principal; | ||
7 | |||
8 | public class MsiE2EFixture | ||
9 | { | ||
10 | const string RequiredEnvironmentVariableName = "RuntimeTestsEnabled"; | ||
11 | |||
12 | public MsiE2EFixture() | ||
13 | { | ||
14 | using var identity = WindowsIdentity.GetCurrent(); | ||
15 | var principal = new WindowsPrincipal(identity); | ||
16 | if (!principal.IsInRole(WindowsBuiltInRole.Administrator)) | ||
17 | { | ||
18 | throw new InvalidOperationException("These tests must run elevated."); | ||
19 | } | ||
20 | |||
21 | var testsEnabledString = Environment.GetEnvironmentVariable(RequiredEnvironmentVariableName); | ||
22 | if (!bool.TryParse(testsEnabledString, out var testsEnabled) || !testsEnabled) | ||
23 | { | ||
24 | throw new InvalidOperationException($"These tests affect machine state. Set the {RequiredEnvironmentVariableName} environment variable to true to accept the consequences."); | ||
25 | } | ||
26 | } | ||
27 | } | ||
28 | } | ||
diff --git a/src/test/msi/WixToolsetTest.MsiE2E/MsiE2ETests.cs b/src/test/msi/WixToolsetTest.MsiE2E/MsiE2ETests.cs new file mode 100644 index 00000000..22f2173b --- /dev/null +++ b/src/test/msi/WixToolsetTest.MsiE2E/MsiE2ETests.cs | |||
@@ -0,0 +1,44 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolsetTest.MsiE2E | ||
4 | { | ||
5 | using System; | ||
6 | using System.Collections.Generic; | ||
7 | using WixTestTools; | ||
8 | using Xunit; | ||
9 | using Xunit.Abstractions; | ||
10 | |||
11 | [Collection("MsiE2E")] | ||
12 | public abstract class MsiE2ETests : WixTestBase, IDisposable | ||
13 | { | ||
14 | protected MsiE2ETests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) | ||
15 | { | ||
16 | } | ||
17 | |||
18 | private Stack<IDisposable> Installers { get; } = new Stack<IDisposable>(); | ||
19 | |||
20 | protected PackageInstaller CreatePackageInstaller(string filename) | ||
21 | { | ||
22 | var installer = new PackageInstaller(this.TestContext, filename); | ||
23 | this.Installers.Push(installer); | ||
24 | return installer; | ||
25 | } | ||
26 | |||
27 | public void Dispose() | ||
28 | { | ||
29 | while (this.Installers.TryPop(out var installer)) | ||
30 | { | ||
31 | try | ||
32 | { | ||
33 | installer.Dispose(); | ||
34 | } | ||
35 | catch { } | ||
36 | } | ||
37 | } | ||
38 | } | ||
39 | |||
40 | [CollectionDefinition("MsiE2E", DisableParallelization = true)] | ||
41 | public class MsiE2ECollectionDefinition : ICollectionFixture<MsiE2EFixture> | ||
42 | { | ||
43 | } | ||
44 | } | ||
diff --git a/src/test/msi/WixToolsetTest.MsiE2E/UtilExtensionUserTests.cs b/src/test/msi/WixToolsetTest.MsiE2E/UtilExtensionUserTests.cs new file mode 100644 index 00000000..21491858 --- /dev/null +++ b/src/test/msi/WixToolsetTest.MsiE2E/UtilExtensionUserTests.cs | |||
@@ -0,0 +1,162 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolsetTest.MsiE2E | ||
4 | { | ||
5 | using System; | ||
6 | using WixTestTools; | ||
7 | using Xunit; | ||
8 | using Xunit.Abstractions; | ||
9 | |||
10 | public class UtilExtensionUserTests : MsiE2ETests | ||
11 | { | ||
12 | public UtilExtensionUserTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { } | ||
13 | |||
14 | const string TempDomain = "USERDOMAIN"; | ||
15 | const string TempUsername = "USERNAME"; | ||
16 | |||
17 | // Verify that the users specified in the authoring are created as expected. | ||
18 | [Fact] | ||
19 | public void CanInstallAndUninstallUsers() | ||
20 | { | ||
21 | var arguments = new string[] | ||
22 | { | ||
23 | $"TEMPDOMAIN={Environment.GetEnvironmentVariable(TempDomain)}", | ||
24 | $"TEMPUSERNAME={Environment.GetEnvironmentVariable(TempUsername)}", | ||
25 | }; | ||
26 | var productA = this.CreatePackageInstaller("ProductA"); | ||
27 | |||
28 | productA.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS, arguments); | ||
29 | |||
30 | // Validate New User Information. | ||
31 | UserVerifier.VerifyUserInformation(String.Empty, "testName1", true, false, false); | ||
32 | UserVerifier.VerifyUserIsMemberOf(String.Empty, "testName1", "Administrators", "Power Users"); | ||
33 | |||
34 | UserVerifier.VerifyUserInformation(String.Empty, "testName2", true, true, true); | ||
35 | UserVerifier.VerifyUserIsMemberOf(String.Empty, "testName2", "Power Users"); | ||
36 | |||
37 | UserVerifier.VerifyUserIsMemberOf(Environment.GetEnvironmentVariable(TempDomain), Environment.GetEnvironmentVariable(TempUsername), "Power Users"); | ||
38 | |||
39 | productA.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS, arguments); | ||
40 | |||
41 | // Verify Users marked as RemoveOnUninstall were removed. | ||
42 | Assert.False(UserVerifier.UserExists(String.Empty, "testName1"), String.Format("User '{0}' was not removed on Uninstall", "testName1")); | ||
43 | Assert.True(UserVerifier.UserExists(String.Empty, "testName2"), String.Format("User '{0}' was removed on Uninstall", "testName2")); | ||
44 | |||
45 | // clean up | ||
46 | UserVerifier.DeleteLocalUser("testName2"); | ||
47 | |||
48 | UserVerifier.VerifyUserIsNotMemberOf(Environment.GetEnvironmentVariable(TempDomain), Environment.GetEnvironmentVariable(TempUsername), "Power Users"); | ||
49 | } | ||
50 | |||
51 | // Verify the rollback action reverts all Users changes. | ||
52 | [Fact] | ||
53 | public void CanRollbackUsers() | ||
54 | { | ||
55 | var arguments = new string[] | ||
56 | { | ||
57 | $"TEMPDOMAIN={Environment.GetEnvironmentVariable(TempDomain)}", | ||
58 | $"TEMPUSERNAME={Environment.GetEnvironmentVariable(TempUsername)}", | ||
59 | }; | ||
60 | var productFail = this.CreatePackageInstaller("ProductFail"); | ||
61 | |||
62 | // make sure the user accounts are deleted before we start | ||
63 | UserVerifier.DeleteLocalUser("testName1"); | ||
64 | UserVerifier.DeleteLocalUser("testName2"); | ||
65 | UserVerifier.VerifyUserIsNotMemberOf(Environment.GetEnvironmentVariable(TempDomain), Environment.GetEnvironmentVariable(TempUsername), "Power Users"); | ||
66 | |||
67 | productFail.InstallProduct(MSIExec.MSIExecReturnCode.ERROR_INSTALL_FAILURE, arguments); | ||
68 | |||
69 | // Verify Users marked as RemoveOnUninstall were removed. | ||
70 | Assert.False(UserVerifier.UserExists(String.Empty, "testName1"), String.Format("User '{0}' was not removed on Rollback", "testName1")); | ||
71 | Assert.False(UserVerifier.UserExists(String.Empty, "testName2"), String.Format("User '{0}' was not removed on Rollback", "testName2")); | ||
72 | |||
73 | UserVerifier.VerifyUserIsNotMemberOf(Environment.GetEnvironmentVariable(TempDomain), Environment.GetEnvironmentVariable(TempUsername), "Power Users"); | ||
74 | } | ||
75 | |||
76 | // Verify that the users specified in the authoring are created as expected on repair. | ||
77 | [Fact(Skip = "Test demonstrates failure")] | ||
78 | public void CanRepairUsers() | ||
79 | { | ||
80 | var arguments = new string[] | ||
81 | { | ||
82 | $"TEMPDOMAIN={Environment.GetEnvironmentVariable(TempDomain)}", | ||
83 | $"TEMPUSERNAME={Environment.GetEnvironmentVariable(TempUsername)}", | ||
84 | }; | ||
85 | var productA = this.CreatePackageInstaller("ProductA"); | ||
86 | |||
87 | productA.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS, arguments); | ||
88 | |||
89 | UserVerifier.DeleteLocalUser("testName1"); | ||
90 | UserVerifier.SetUserInformation(String.Empty, "testName2", true, false, false); | ||
91 | |||
92 | productA.RepairProduct(MSIExec.MSIExecReturnCode.SUCCESS, arguments); | ||
93 | |||
94 | // Validate New User Information. | ||
95 | UserVerifier.VerifyUserInformation(String.Empty, "testName1", true, false, false); | ||
96 | UserVerifier.VerifyUserIsMemberOf(String.Empty, "testName1", "Administrators", "Power Users"); | ||
97 | |||
98 | UserVerifier.VerifyUserInformation(String.Empty, "testName2", true, true, true); | ||
99 | UserVerifier.VerifyUserIsMemberOf(String.Empty, "testName2", "Power Users"); | ||
100 | |||
101 | UserVerifier.VerifyUserIsMemberOf(Environment.GetEnvironmentVariable(TempDomain), Environment.GetEnvironmentVariable(TempUsername), "Power Users"); | ||
102 | |||
103 | productA.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS, arguments); | ||
104 | |||
105 | // Verify Users marked as RemoveOnUninstall were removed. | ||
106 | Assert.False(UserVerifier.UserExists(String.Empty, "testName1"), String.Format("User '{0}' was not removed on Uninstall", "testName1")); | ||
107 | Assert.True(UserVerifier.UserExists(String.Empty, "testName2"), String.Format("User '{0}' was removed on Uninstall", "testName2")); | ||
108 | |||
109 | // clean up | ||
110 | UserVerifier.DeleteLocalUser("testName2"); | ||
111 | |||
112 | UserVerifier.VerifyUserIsNotMemberOf(Environment.GetEnvironmentVariable(TempDomain), Environment.GetEnvironmentVariable(TempUsername), "Power Users"); | ||
113 | } | ||
114 | |||
115 | // Verify that Installation fails if FailIfExisits is set. | ||
116 | [Fact] | ||
117 | public void FailsIfUserExists() | ||
118 | { | ||
119 | var productFailIfExists = this.CreatePackageInstaller("ProductFailIfExists"); | ||
120 | |||
121 | // Create 'existinguser' | ||
122 | UserVerifier.CreateLocalUser("existinguser", "test123!@#"); | ||
123 | |||
124 | try | ||
125 | { | ||
126 | productFailIfExists.InstallProduct(MSIExec.MSIExecReturnCode.ERROR_INSTALL_FAILURE); | ||
127 | |||
128 | // Verify User still exists. | ||
129 | bool userExists = UserVerifier.UserExists(String.Empty, "existinguser"); | ||
130 | |||
131 | Assert.True(userExists, String.Format("User '{0}' was removed on Rollback", "existinguser")); | ||
132 | } | ||
133 | finally | ||
134 | { | ||
135 | // clean up | ||
136 | UserVerifier.DeleteLocalUser("existinguser"); | ||
137 | } | ||
138 | |||
139 | } | ||
140 | |||
141 | // Verify that a user cannot be created on a domain on which you dont have create user permission. | ||
142 | [Fact] | ||
143 | public void FailsIfRestrictedDomain() | ||
144 | { | ||
145 | var productRestrictedDomain = this.CreatePackageInstaller("ProductRestrictedDomain"); | ||
146 | |||
147 | string logFile = productRestrictedDomain.InstallProduct(MSIExec.MSIExecReturnCode.ERROR_INSTALL_FAILURE, "TEMPDOMAIN=DOESNOTEXIST"); | ||
148 | |||
149 | // Verify expected error message in the log file | ||
150 | Assert.True(LogVerifier.MessageInLogFile(logFile, "ConfigureUsers: Failed to check existence of domain: DOESNOTEXIST, user: testName1 (error code 0x800706ba) - continuing")); | ||
151 | } | ||
152 | |||
153 | // Verify that adding a user to a non-existent group does not fail the install when non-vital. | ||
154 | [Fact] | ||
155 | public void IgnoresMissingGroupWhenNonVital() | ||
156 | { | ||
157 | var productNonVitalGroup = this.CreatePackageInstaller("ProductNonVitalUserGroup"); | ||
158 | |||
159 | productNonVitalGroup.InstallProduct(); | ||
160 | } | ||
161 | } | ||
162 | } | ||
diff --git a/src/test/msi/WixToolsetTest.MsiE2E/WixToolsetTest.MsiE2E.csproj b/src/test/msi/WixToolsetTest.MsiE2E/WixToolsetTest.MsiE2E.csproj new file mode 100644 index 00000000..ccf98042 --- /dev/null +++ b/src/test/msi/WixToolsetTest.MsiE2E/WixToolsetTest.MsiE2E.csproj | |||
@@ -0,0 +1,31 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
3 | |||
4 | <Project Sdk="Microsoft.NET.Sdk"> | ||
5 | <PropertyGroup> | ||
6 | <TargetFramework>netcoreapp3.1</TargetFramework> | ||
7 | <PlatformTarget>x64</PlatformTarget> | ||
8 | <RollForward>Major</RollForward> | ||
9 | </PropertyGroup> | ||
10 | |||
11 | <ItemGroup> | ||
12 | <Content Include="runtests.cmd" CopyToOutputDirectory="PreserveNewest" /> | ||
13 | </ItemGroup> | ||
14 | |||
15 | <ItemGroup> | ||
16 | <ProjectReference Include="..\..\burn\WixTestTools\WixTestTools.csproj" /> | ||
17 | </ItemGroup> | ||
18 | |||
19 | <ItemGroup> | ||
20 | <PackageReference Include="Microsoft.Win32.Registry" /> | ||
21 | <PackageReference Include="System.Security.Principal.Windows" /> | ||
22 | <PackageReference Include="WixBuildTools.TestSupport" /> | ||
23 | <PackageReference Include="WixToolset.Data" /> | ||
24 | </ItemGroup> | ||
25 | |||
26 | <ItemGroup> | ||
27 | <PackageReference Include="Microsoft.NET.Test.Sdk" /> | ||
28 | <PackageReference Include="xunit" /> | ||
29 | <PackageReference Include="xunit.runner.visualstudio" PrivateAssets="All" /> | ||
30 | </ItemGroup> | ||
31 | </Project> | ||
diff --git a/src/test/msi/WixToolsetTest.MsiE2E/runtests.cmd b/src/test/msi/WixToolsetTest.MsiE2E/runtests.cmd new file mode 100644 index 00000000..f609ebe4 --- /dev/null +++ b/src/test/msi/WixToolsetTest.MsiE2E/runtests.cmd | |||
@@ -0,0 +1,2 @@ | |||
1 | SET RuntimeTestsEnabled=true | ||
2 | dotnet test WixToolsetTest.MsiE2E.dll -v normal \ No newline at end of file | ||
diff --git a/src/test/msi/test_msi.cmd b/src/test/msi/test_msi.cmd new file mode 100644 index 00000000..bb9d0162 --- /dev/null +++ b/src/test/msi/test_msi.cmd | |||
@@ -0,0 +1,23 @@ | |||
1 | @setlocal | ||
2 | @pushd %~dp0 | ||
3 | |||
4 | @set _RESULT=0 | ||
5 | @set _C=Debug | ||
6 | @set _L=%~dp0..\..\..\build\logs | ||
7 | :parse_args | ||
8 | @if /i "%1"=="release" set _C=Release | ||
9 | @if /i "%1"=="test" set RuntimeTestsEnabled=true | ||
10 | @if not "%1"=="" shift & goto parse_args | ||
11 | |||
12 | @echo Msi integration tests %_C% | ||
13 | |||
14 | msbuild -t:Build -Restore -p:Configuration=%_C% -warnaserror -bl:%_L%\test_msi_build.binlog || exit /b | ||
15 | msbuild -t:Build -Restore TestData\TestData.proj -p:Configuration=%_C% -m -bl:%_L%\test_msi_data_build.binlog || exit /b | ||
16 | |||
17 | @if not "%RuntimeTestsEnabled%"=="true" goto :LExit | ||
18 | |||
19 | dotnet test -c %_C% --no-build WixToolsetTest.MsiE2E -l "trx;LogFileName=%_L%\TestResults\WixToolsetTest.MsiE2E.trx" || exit /b | ||
20 | |||
21 | :LExit | ||
22 | @popd | ||
23 | @endlocal | ||
diff --git a/src/test/test.cmd b/src/test/test.cmd index 4c80ba7d..0b29f240 100644 --- a/src/test/test.cmd +++ b/src/test/test.cmd | |||
@@ -11,6 +11,7 @@ | |||
11 | @if not "%RuntimeTestsEnabled%"=="true" echo Build integration tests %_C% | 11 | @if not "%RuntimeTestsEnabled%"=="true" echo Build integration tests %_C% |
12 | @if "%RuntimeTestsEnabled%"=="true" set _T=test&echo Run integration tests %_C% | 12 | @if "%RuntimeTestsEnabled%"=="true" set _T=test&echo Run integration tests %_C% |
13 | 13 | ||
14 | @call msi\test_msi.cmd %_C% %_T% || exit /b | ||
14 | @call burn\test_burn.cmd %_C% %_T% || exit /b | 15 | @call burn\test_burn.cmd %_C% %_T% || exit /b |
15 | 16 | ||
16 | msbuild -t:Restore dtf\DtfE2ETests.sln -p:Configuration=%_C% -nologo -m -warnaserror -bl:%_L%\dtfe2etests.binlog || exit /b | 17 | msbuild -t:Restore dtf\DtfE2ETests.sln -p:Configuration=%_C% -nologo -m -warnaserror -bl:%_L%\dtfe2etests.binlog || exit /b |
diff --git a/src/testresultfilelist.txt b/src/testresultfilelist.txt index 472a8d1d..60fc168b 100644 --- a/src/testresultfilelist.txt +++ b/src/testresultfilelist.txt | |||
@@ -17,5 +17,6 @@ build/logs/TestResults/WixToolsetTest.Dnc.HostGenerator.trx | |||
17 | build/logs/TestResults/WixToolsetTest.Heat.trx | 17 | build/logs/TestResults/WixToolsetTest.Heat.trx |
18 | build/logs/TestResults/WixToolsetTest.ManagedHost.trx | 18 | build/logs/TestResults/WixToolsetTest.ManagedHost.trx |
19 | build/logs/TestResults/WixToolsetTest.Mba.Core.trx | 19 | build/logs/TestResults/WixToolsetTest.Mba.Core.trx |
20 | build/logs/TestResults/WixToolsetTest.MsiE2E.trx | ||
20 | build/logs/TestResults/WixToolsetTest.Sdk.trx | 21 | build/logs/TestResults/WixToolsetTest.Sdk.trx |
21 | build/logs/TestResults/WixToolsetTest.WixE2ETests.trx \ No newline at end of file | 22 | build/logs/TestResults/WixToolsetTest.WixE2ETests.trx \ No newline at end of file |