1 // Copyright (c) .NET Foundation. All rights reserved.
2 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3 
4 using System;
5 using System.Collections.Generic;
6 using System.IO;
7 using System.Linq;
8 using System.Text;
9 using System.Threading.Tasks;
10 using Microsoft.Build.Framework;
11 using Xunit;
12 
13 namespace Microsoft.NuGet.Build.Tasks.Tests
14 {
15     internal static class AssertHelpers
16     {
AssertCountOf(int expectedCount, IEnumerable<ITaskItem> items)17         public static void AssertCountOf(int expectedCount, IEnumerable<ITaskItem> items)
18         {
19             Assert.True(items.Count() == expectedCount,
20                 $"Expected {expectedCount} items, but actually got {items.Count()} items:" + Environment.NewLine + string.Join(Environment.NewLine, items.Select(i => i.ItemSpec)));
21         }
22 
23         /// <summary>
24         /// Asserts that the expected path ends with our actual path. "Ends with" in this case is defined by path
25         /// components, so "Directory\File" doesn't end with "ile", to prevent any bugs where path components get mangled.
26         /// </summary>
PathEndsWith(string expectedPath, string actualPath)27         public static void PathEndsWith(string expectedPath, string actualPath)
28         {
29             // We could implement this with a simple Assert.True(...EndsWithPath),
30             // but that results in less user-friendly output from the test than a smarter call to
31             // Assert.EndsWith
32             if (!actualPath.EndsWithPath(expectedPath))
33             {
34                 Assert.EndsWith("\\" + expectedPath, actualPath);
35 
36                 // If we get out of sync with this function or EndsWithPath, that Assert might not
37                 // fail. In that case, fail the test.
38                 throw new Exception("The Assert.EndsWith in the previous line should have failed.");
39             }
40         }
41 
42         /// <summary>
43         /// Returns that the expected path ends with our actual path. "Ends with" in this case is defined by path
44         /// components, so "Directory\File" doesn't end with "ile", to prevent any bugs where path components get mangled.
45         /// </summary>
EndsWithPath(this string path, string suffix)46         public static bool EndsWithPath(this string path, string suffix)
47         {
48             return path == suffix || path.EndsWith("\\" + suffix);
49         }
50 
AssertNoTargetPaths(IEnumerable<ITaskItem> items)51         public static void AssertNoTargetPaths(IEnumerable<ITaskItem> items)
52         {
53             foreach (var item in items)
54             {
55                 Assert.Equal("", item.GetMetadata("DestinationSubDirectory"));
56                 Assert.Equal("", item.GetMetadata("TargetPath"));
57             }
58         }
59 
AssertConsistentTargetPaths(IEnumerable<ITaskItem> items)60         public static void AssertConsistentTargetPaths(IEnumerable<ITaskItem> items)
61         {
62             var mapToItem = new Dictionary<string, ITaskItem>(StringComparer.OrdinalIgnoreCase);
63 
64             foreach (var item in items)
65             {
66                 string effectiveTargetPath = item.GetMetadata("TargetPath");
67 
68                 if (string.IsNullOrEmpty(effectiveTargetPath))
69                 {
70                     effectiveTargetPath = Path.GetFileName(item.ItemSpec);
71                 }
72 
73                 ITaskItem conflictingItem;
74                 if (mapToItem.TryGetValue(effectiveTargetPath, out conflictingItem))
75                 {
76                     Assert.True(conflictingItem == null, $"Item {item.ItemSpec} and {conflictingItem.ItemSpec} have the same TargetPath.");
77                 }
78 
79                 mapToItem.Add(effectiveTargetPath, item);
80             }
81         }
82     }
83 }
84