1 // Copyright (c) Microsoft. All rights reserved. 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 //----------------------------------------------------------------------- 4 // </copyright> 5 // <summary>Tests for the ProjectUsingTaskElement class.</summary> 6 //----------------------------------------------------------------------- 7 8 using System; 9 using System.Collections.Generic; 10 using System.IO; 11 using System.Reflection; 12 using System.Text; 13 using System.Xml; 14 15 using Microsoft.Build.Construction; 16 using Microsoft.Build.Shared; 17 18 using InvalidProjectFileException = Microsoft.Build.Exceptions.InvalidProjectFileException; 19 using Xunit; 20 21 namespace Microsoft.Build.UnitTests.OM.Construction 22 { 23 /// <summary> 24 /// Tests for the ProjectUsingTaskElement class 25 /// </summary> 26 public class ProjectUsingTaskElement_Tests 27 { 28 /// <summary> 29 /// Read project with no usingtasks 30 /// </summary> 31 [Fact] ReadNone()32 public void ReadNone() 33 { 34 ProjectRootElement project = ProjectRootElement.Create(); 35 36 Assert.Equal(null, project.UsingTasks.GetEnumerator().Current); 37 } 38 39 /// <summary> 40 /// Read usingtask with no task name attribute 41 /// </summary> 42 [Fact] ReadInvalidMissingTaskName()43 public void ReadInvalidMissingTaskName() 44 { 45 Assert.Throws<InvalidProjectFileException>(() => 46 { 47 string content = @" 48 <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' > 49 <UsingTask AssemblyFile='af'/> 50 </Project> 51 "; 52 53 ProjectRootElement.Create(XmlReader.Create(new StringReader(content))); 54 } 55 ); 56 } 57 /// <summary> 58 /// Read usingtask with empty task name attribute 59 /// </summary> 60 [Fact] ReadInvalidEmptyTaskName()61 public void ReadInvalidEmptyTaskName() 62 { 63 Assert.Throws<InvalidProjectFileException>(() => 64 { 65 string content = @" 66 <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' > 67 <UsingTask TaskName='' AssemblyFile='af'/> 68 </Project> 69 "; 70 71 ProjectRootElement.Create(XmlReader.Create(new StringReader(content))); 72 } 73 ); 74 } 75 /// <summary> 76 /// Read usingtask with unexpected attribute 77 /// </summary> 78 [Fact] ReadInvalidAttribute()79 public void ReadInvalidAttribute() 80 { 81 Assert.Throws<InvalidProjectFileException>(() => 82 { 83 string content = @" 84 <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' > 85 <UsingTask TaskName='t' AssemblyFile='af' X='Y'/> 86 </Project> 87 "; 88 89 ProjectRootElement.Create(XmlReader.Create(new StringReader(content))); 90 } 91 ); 92 } 93 /// <summary> 94 /// Read usingtask with neither AssemblyFile nor AssemblyName attributes 95 /// </summary> 96 [Fact] ReadInvalidMissingAssemblyFileAssemblyName()97 public void ReadInvalidMissingAssemblyFileAssemblyName() 98 { 99 Assert.Throws<InvalidProjectFileException>(() => 100 { 101 string content = @" 102 <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' > 103 <UsingTask TaskName='t'/> 104 </Project> 105 "; 106 107 ProjectRootElement.Create(XmlReader.Create(new StringReader(content))); 108 } 109 ); 110 } 111 /// <summary> 112 /// Read usingtask with only empty AssemblyFile attribute 113 /// </summary> 114 [Fact] ReadInvalidEmptyAssemblyFile()115 public void ReadInvalidEmptyAssemblyFile() 116 { 117 Assert.Throws<InvalidProjectFileException>(() => 118 { 119 string content = @" 120 <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' > 121 <UsingTask TaskName='t' AssemblyFile=''/> 122 </Project> 123 "; 124 125 ProjectRootElement.Create(XmlReader.Create(new StringReader(content))); 126 } 127 ); 128 } 129 /// <summary> 130 /// Read usingtask with empty AssemblyFile attribute but AssemblyName present 131 /// </summary> 132 [Fact] ReadInvalidEmptyAssemblyFileAndAssemblyNameNotEmpty()133 public void ReadInvalidEmptyAssemblyFileAndAssemblyNameNotEmpty() 134 { 135 Assert.Throws<InvalidProjectFileException>(() => 136 { 137 string content = @" 138 <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' > 139 <UsingTask TaskName='t' AssemblyFile='' AssemblyName='n'/> 140 </Project> 141 "; 142 143 ProjectRootElement.Create(XmlReader.Create(new StringReader(content))); 144 } 145 ); 146 } 147 /// <summary> 148 /// Read usingtask with only empty AssemblyName attribute but AssemblyFile present 149 /// </summary> 150 [Fact] ReadInvalidEmptyAssemblyNameAndAssemblyFileNotEmpty()151 public void ReadInvalidEmptyAssemblyNameAndAssemblyFileNotEmpty() 152 { 153 Assert.Throws<InvalidProjectFileException>(() => 154 { 155 string content = @" 156 <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' > 157 <UsingTask TaskName='t' AssemblyName='' AssemblyFile='f'/> 158 </Project> 159 "; 160 161 ProjectRootElement.Create(XmlReader.Create(new StringReader(content))); 162 } 163 ); 164 } 165 /// <summary> 166 /// Read usingtask with both AssemblyName and AssemblyFile attributes 167 /// </summary> 168 [Fact] ReadInvalidBothAssemblyFileAssemblyName()169 public void ReadInvalidBothAssemblyFileAssemblyName() 170 { 171 Assert.Throws<InvalidProjectFileException>(() => 172 { 173 string content = @" 174 <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' > 175 <UsingTask TaskName='t' AssemblyName='an' AssemblyFile='af'/> 176 </Project> 177 "; 178 179 ProjectRootElement.Create(XmlReader.Create(new StringReader(content))); 180 } 181 ); 182 } 183 /// <summary> 184 /// Read usingtask with both AssemblyName and AssemblyFile attributes but both are empty 185 /// </summary> 186 [Fact] ReadInvalidBothEmptyAssemblyFileEmptyAssemblyNameBoth()187 public void ReadInvalidBothEmptyAssemblyFileEmptyAssemblyNameBoth() 188 { 189 Assert.Throws<InvalidProjectFileException>(() => 190 { 191 string content = @" 192 <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' > 193 <UsingTask TaskName='t' AssemblyName='' AssemblyFile=''/> 194 </Project> 195 "; 196 197 ProjectRootElement.Create(XmlReader.Create(new StringReader(content))); 198 } 199 ); 200 } 201 /// <summary> 202 /// Read usingtask with assembly file 203 /// </summary> 204 [Fact] ReadBasicUsingTaskAssemblyFile()205 public void ReadBasicUsingTaskAssemblyFile() 206 { 207 ProjectUsingTaskElement usingTask = GetUsingTaskAssemblyFile(); 208 209 Assert.Equal("t1", usingTask.TaskName); 210 Assert.Equal("af", usingTask.AssemblyFile); 211 Assert.Equal(String.Empty, usingTask.AssemblyName); 212 Assert.Equal(String.Empty, usingTask.Condition); 213 } 214 215 /// <summary> 216 /// Read usingtask with assembly name 217 /// </summary> 218 [Fact] ReadBasicUsingTaskAssemblyName()219 public void ReadBasicUsingTaskAssemblyName() 220 { 221 ProjectUsingTaskElement usingTask = GetUsingTaskAssemblyName(); 222 223 Assert.Equal("t2", usingTask.TaskName); 224 Assert.Equal(String.Empty, usingTask.AssemblyFile); 225 Assert.Equal("an", usingTask.AssemblyName); 226 Assert.Equal("c", usingTask.Condition); 227 } 228 229 /// <summary> 230 /// Read usingtask with task factory, required runtime and required platform 231 /// </summary> 232 [Fact] ReadBasicUsingTaskFactoryRuntimeAndPlatform()233 public void ReadBasicUsingTaskFactoryRuntimeAndPlatform() 234 { 235 ProjectUsingTaskElement usingTask = GetUsingTaskFactoryRuntimeAndPlatform(); 236 237 Assert.Equal("t2", usingTask.TaskName); 238 Assert.Equal(String.Empty, usingTask.AssemblyFile); 239 Assert.Equal("an", usingTask.AssemblyName); 240 Assert.Equal("c", usingTask.Condition); 241 Assert.Equal("AssemblyFactory", usingTask.TaskFactory); 242 } 243 244 /// <summary> 245 /// Verify that passing in string.empty or null for TaskFactory will remove the element from the xml. 246 /// </summary> 247 [Fact] RemoveUsingTaskFactoryRuntimeAndPlatform()248 public void RemoveUsingTaskFactoryRuntimeAndPlatform() 249 { 250 ProjectUsingTaskElement usingTask = GetUsingTaskFactoryRuntimeAndPlatform(); 251 252 string value = null; 253 VerifyAttributesRemoved(usingTask, value); 254 255 usingTask = GetUsingTaskFactoryRuntimeAndPlatform(); 256 value = String.Empty; 257 VerifyAttributesRemoved(usingTask, value); 258 } 259 260 /// <summary> 261 /// Set assembly file on a usingtask that already has assembly file 262 /// </summary> 263 [Fact] SetUsingTaskAssemblyFileOnUsingTaskAssemblyFile()264 public void SetUsingTaskAssemblyFileOnUsingTaskAssemblyFile() 265 { 266 ProjectUsingTaskElement usingTask = GetUsingTaskAssemblyFile(); 267 Helpers.ClearDirtyFlag(usingTask.ContainingProject); 268 269 usingTask.AssemblyFile = "afb"; 270 Assert.Equal("afb", usingTask.AssemblyFile); 271 Assert.Equal(true, usingTask.ContainingProject.HasUnsavedChanges); 272 } 273 274 /// <summary> 275 /// Set assembly name on a usingtask that already has assembly name 276 /// </summary> 277 [Fact] SetUsingTaskAssemblyNameOnUsingTaskAssemblyName()278 public void SetUsingTaskAssemblyNameOnUsingTaskAssemblyName() 279 { 280 ProjectUsingTaskElement usingTask = GetUsingTaskAssemblyName(); 281 Helpers.ClearDirtyFlag(usingTask.ContainingProject); 282 283 usingTask.AssemblyName = "anb"; 284 Assert.Equal("anb", usingTask.AssemblyName); 285 Assert.Equal(true, usingTask.ContainingProject.HasUnsavedChanges); 286 } 287 288 /// <summary> 289 /// Set assembly file on a usingtask that already has assembly name 290 /// </summary> 291 [Fact] SetUsingTaskAssemblyFileOnUsingTaskAssemblyName()292 public void SetUsingTaskAssemblyFileOnUsingTaskAssemblyName() 293 { 294 Assert.Throws<InvalidOperationException>(() => 295 { 296 ProjectUsingTaskElement usingTask = GetUsingTaskAssemblyName(); 297 298 usingTask.AssemblyFile = "afb"; 299 } 300 ); 301 } 302 /// <summary> 303 /// Set assembly name on a usingtask that already has assembly file 304 /// </summary> 305 [Fact] SetUsingTaskAssemblyNameOnUsingTaskAssemblyFile()306 public void SetUsingTaskAssemblyNameOnUsingTaskAssemblyFile() 307 { 308 Assert.Throws<InvalidOperationException>(() => 309 { 310 ProjectUsingTaskElement usingTask = GetUsingTaskAssemblyFile(); 311 312 usingTask.AssemblyName = "anb"; 313 } 314 ); 315 } 316 /// <summary> 317 /// Set task name 318 /// </summary> 319 [Fact] SetTaskName()320 public void SetTaskName() 321 { 322 ProjectRootElement project = ProjectRootElement.Create(); 323 ProjectUsingTaskElement usingTask = project.AddUsingTask("t", "af", null); 324 Helpers.ClearDirtyFlag(usingTask.ContainingProject); 325 326 usingTask.TaskName = "tt"; 327 Assert.Equal("tt", usingTask.TaskName); 328 Assert.Equal(true, usingTask.ContainingProject.HasUnsavedChanges); 329 } 330 331 /// <summary> 332 /// Set condition 333 /// </summary> 334 [Fact] SetCondition()335 public void SetCondition() 336 { 337 ProjectRootElement project = ProjectRootElement.Create(); 338 ProjectUsingTaskElement usingTask = project.AddUsingTask("t", "af", null); 339 Helpers.ClearDirtyFlag(usingTask.ContainingProject); 340 341 usingTask.Condition = "c"; 342 Assert.Equal("c", usingTask.Condition); 343 Assert.Equal(true, usingTask.ContainingProject.HasUnsavedChanges); 344 } 345 346 /// <summary> 347 /// Set task factory 348 /// </summary> 349 [Fact] SetTaskFactory()350 public void SetTaskFactory() 351 { 352 ProjectRootElement project = ProjectRootElement.Create(); 353 ProjectUsingTaskElement usingTask = project.AddUsingTask("t", "af", null); 354 Helpers.ClearDirtyFlag(usingTask.ContainingProject); 355 356 usingTask.TaskFactory = "AssemblyFactory"; 357 Assert.Equal("AssemblyFactory", usingTask.TaskFactory); 358 Assert.Equal(true, usingTask.ContainingProject.HasUnsavedChanges); 359 } 360 361 /// <summary> 362 /// Make sure there is an exception when there are multiple parameter groups in the using task tag. 363 /// </summary> 364 [Fact] DuplicateParameterGroup()365 public void DuplicateParameterGroup() 366 { 367 Assert.Throws<InvalidProjectFileException>(() => 368 { 369 string content = @" 370 <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' > 371 <UsingTask TaskName='t2' AssemblyName='an' Condition='c' TaskFactory='AssemblyFactory'> 372 <ParameterGroup/> 373 <ParameterGroup/> 374 </UsingTask> 375 </Project> 376 "; 377 ProjectRootElement project = ProjectRootElement.Create(XmlReader.Create(new StringReader(content))); 378 Assert.True(false); 379 } 380 ); 381 } 382 /// <summary> 383 /// Make sure there is an exception when there are multiple task groups in the using task tag. 384 /// </summary> 385 [Fact] DuplicateTaskGroup()386 public void DuplicateTaskGroup() 387 { 388 Assert.Throws<InvalidProjectFileException>(() => 389 { 390 string content = @" 391 <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' > 392 <UsingTask TaskName='t2' AssemblyName='an' Condition='c' TaskFactory='AssemblyFactory'> 393 <Task/> 394 <Task/> 395 </UsingTask> 396 </Project> 397 "; 398 ProjectRootElement project = ProjectRootElement.Create(XmlReader.Create(new StringReader(content))); 399 Assert.True(false); 400 } 401 ); 402 } 403 /// <summary> 404 /// Make sure there is an exception when there is an unknown child 405 /// </summary> 406 [Fact] UnknownChild()407 public void UnknownChild() 408 { 409 Assert.Throws<InvalidProjectFileException>(() => 410 { 411 string content = @" 412 <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' > 413 <UsingTask TaskName='t2' AssemblyName='an' Condition='c' TaskFactory='AssemblyFactory'> 414 <IAMUNKNOWN/> 415 </UsingTask> 416 </Project> 417 "; 418 ProjectRootElement project = ProjectRootElement.Create(XmlReader.Create(new StringReader(content))); 419 Assert.True(false); 420 } 421 ); 422 } 423 /// <summary> 424 /// Make sure there is an no exception when there are children in the using task 425 /// </summary> 426 [Fact] WorksWithChildren()427 public void WorksWithChildren() 428 { 429 string content = @" 430 <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' > 431 <UsingTask TaskName='t2' AssemblyName='an' Condition='c' TaskFactory='AssemblyFactory'> 432 <ParameterGroup> 433 <MyParameter/> 434 </ParameterGroup> 435 <Task> 436 RANDOM GOO 437 </Task> 438 </UsingTask> 439 </Project> 440 "; 441 442 ProjectRootElement project = ProjectRootElement.Create(XmlReader.Create(new StringReader(content))); 443 ProjectUsingTaskElement usingTask = (ProjectUsingTaskElement)Helpers.GetFirst(project.Children); 444 Assert.NotNull(usingTask); 445 Assert.Equal(2, usingTask.Count); 446 } 447 448 /// <summary> 449 /// Make sure there is an exception when a parameter group is added but no task factory attribute is on the using task 450 /// </summary> 451 [Fact] ExceptionWhenNoTaskFactoryAndHavePG()452 public void ExceptionWhenNoTaskFactoryAndHavePG() 453 { 454 Assert.Throws<InvalidProjectFileException>(() => 455 { 456 string content = @" 457 <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' > 458 <UsingTask TaskName='t2' AssemblyName='an' Condition='c'> 459 <ParameterGroup> 460 <MyParameter/> 461 </ParameterGroup> 462 </UsingTask> 463 </Project> 464 "; 465 466 ProjectRootElement project = ProjectRootElement.Create(XmlReader.Create(new StringReader(content))); 467 ProjectUsingTaskElement usingTask = (ProjectUsingTaskElement)Helpers.GetFirst(project.Children); 468 Assert.True(false); 469 } 470 ); 471 } 472 /// <summary> 473 /// Make sure there is an exception when a parameter group is added but no task factory attribute is on the using task 474 /// </summary> 475 [Fact] ExceptionWhenNoTaskFactoryAndHaveTask()476 public void ExceptionWhenNoTaskFactoryAndHaveTask() 477 { 478 Assert.Throws<InvalidProjectFileException>(() => 479 { 480 string content = @" 481 <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' > 482 <UsingTask TaskName='t2' AssemblyName='an' Condition='c'> 483 <Task/> 484 </UsingTask> 485 </Project> 486 "; 487 488 ProjectRootElement project = ProjectRootElement.Create(XmlReader.Create(new StringReader(content))); 489 ProjectUsingTaskElement usingTask = (ProjectUsingTaskElement)Helpers.GetFirst(project.Children); 490 Assert.True(false); 491 } 492 ); 493 } 494 /// <summary> 495 /// Helper to get a ProjectUsingTaskElement with a task factory, required runtime and required platform 496 /// </summary> GetUsingTaskFactoryRuntimeAndPlatform()497 private static ProjectUsingTaskElement GetUsingTaskFactoryRuntimeAndPlatform() 498 { 499 string content = @" 500 <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' > 501 <UsingTask TaskName='t2' AssemblyName='an' Condition='c' TaskFactory='AssemblyFactory' /> 502 </Project> 503 "; 504 505 ProjectRootElement project = ProjectRootElement.Create(XmlReader.Create(new StringReader(content))); 506 ProjectUsingTaskElement usingTask = (ProjectUsingTaskElement)Helpers.GetFirst(project.Children); 507 return usingTask; 508 } 509 510 /// <summary> 511 /// Helper to get a ProjectUsingTaskElement with an assembly file set 512 /// </summary> GetUsingTaskAssemblyFile()513 private static ProjectUsingTaskElement GetUsingTaskAssemblyFile() 514 { 515 string content = @" 516 <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' > 517 <UsingTask TaskName='t1' AssemblyFile='af' /> 518 <UsingTask TaskName='t2' AssemblyName='an' Condition='c'/> 519 </Project> 520 "; 521 522 ProjectRootElement project = ProjectRootElement.Create(XmlReader.Create(new StringReader(content))); 523 ProjectUsingTaskElement usingTask = (ProjectUsingTaskElement)Helpers.GetFirst(project.Children); 524 return usingTask; 525 } 526 527 /// <summary> 528 /// Helper to get a ProjectUsingTaskElement with an assembly name set 529 /// </summary> GetUsingTaskAssemblyName()530 private static ProjectUsingTaskElement GetUsingTaskAssemblyName() 531 { 532 string content = @" 533 <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' > 534 <UsingTask TaskName='t2' AssemblyName='an' Condition='c'/> 535 </Project> 536 "; 537 538 ProjectRootElement project = ProjectRootElement.Create(XmlReader.Create(new StringReader(content))); 539 ProjectUsingTaskElement usingTask = (ProjectUsingTaskElement)Helpers.GetFirst(project.Children); 540 return usingTask; 541 } 542 543 /// <summary> 544 /// Verify the attributes are removed from the xml when string.empty and null are passed in 545 /// </summary> VerifyAttributesRemoved(ProjectUsingTaskElement usingTask, string value)546 private static void VerifyAttributesRemoved(ProjectUsingTaskElement usingTask, string value) 547 { 548 Assert.True(usingTask.ContainingProject.RawXml.Contains("TaskFactory")); 549 usingTask.TaskFactory = value; 550 Assert.False(usingTask.ContainingProject.RawXml.Contains("TaskFactory")); 551 } 552 } 553 } 554