1 using System; 2 using System.IO; 3 using Microsoft.Build.Framework; 4 using Microsoft.Build.Tasks; 5 using Microsoft.Build.Utilities; 6 using Xunit; 7 8 namespace Microsoft.Build.UnitTests.ResolveAssemblyReference_Tests.VersioningAndUnification.AppConfig 9 { 10 public sealed class SpecificVersionPrimary : ResolveAssemblyReferenceTestFixture 11 { 12 /// <summary> 13 /// In this case, 14 /// - A single primary version-strict reference was passed in to assembly version 1.0.0.0 15 /// - An app.config was passed in that promotes assembly version from 1.0.0.0 to 2.0.0.0 16 /// - Version 1.0.0.0 of the file exists. 17 /// - Version 2.0.0.0 of the file exists. 18 /// Expected: 19 /// - The resulting assembly returned should be 1.0.0.0. 20 /// Rationale: 21 /// Primary references are never unified. This is because: 22 /// (a) The user expects that a primary reference will be respected. 23 /// (b) When FindDependencies is false and AutoUnify is true, we'd have to find all 24 /// dependencies anyway to make things work consistently. This would be a significant 25 /// perf hit when loading large solutions. 26 /// </summary> 27 [Fact] 28 [PlatformSpecific(TestPlatforms.Windows)] Exists()29 public void Exists() 30 { 31 // This WriteLine is a hack. On a slow machine, the Tasks unittest fails because remoting 32 // times out the object used for remoting console writes. Adding a write in the middle of 33 // keeps remoting from timing out the object. 34 Console.WriteLine("Performing VersioningAndUnification.Prerequisite.SpecificVersionPrimary.Exists() test"); 35 36 // Create the engine. 37 MockEngine engine = new MockEngine(); 38 39 ITaskItem[] assemblyNames = new TaskItem[] 40 { 41 new TaskItem("UnifyMe, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") 42 }; 43 assemblyNames[0].SetMetadata("SpecificVersion", "true"); 44 45 // Construct the app.config. 46 string appConfigFile = WriteAppConfig 47 ( 48 " <dependentAssembly>\n" + 49 " <assemblyIdentity name='UnifyMe' PublicKeyToken='b77a5c561934e089' culture='neutral' />\n" + 50 " <bindingRedirect oldVersion='1.0.0.0' newVersion='2.0.0.0' />\n" + 51 " </dependentAssembly>\n" 52 ); 53 54 // Now, pass feed resolved primary references into ResolveAssemblyReference. 55 ResolveAssemblyReference t = new ResolveAssemblyReference(); 56 57 t.BuildEngine = engine; 58 t.Assemblies = assemblyNames; 59 t.SearchPaths = DefaultPaths; 60 t.AppConfigFile = appConfigFile; 61 62 bool succeeded = Execute(t); 63 64 Assert.True(succeeded); 65 Assert.Equal(1, t.ResolvedFiles.Length); 66 AssertNoCase("UnifyMe, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, ProcessorArchitecture=MSIL", t.ResolvedFiles[0].GetMetadata("FusionName")); 67 AssertNoCase(@"{Registry:Software\Microsoft\.NetFramework,v2.0,AssemblyFoldersEx}", t.ResolvedFiles[0].GetMetadata("ResolvedFrom")); 68 69 // Cleanup. 70 File.Delete(appConfigFile); 71 } 72 73 /// <summary> 74 /// In this case, 75 /// - A single primary version-strict reference was passed in to assembly version 1.0.0.0 76 /// - An app.config was passed in that promotes a *different* assembly version name from 77 // 1.0.0.0 to 2.0.0.0 78 /// - Version 1.0.0.0 of the file exists. 79 /// - Version 2.0.0.0 of the file exists. 80 /// Expected: 81 /// -- The resulting assembly returned should be 1.0.0.0. 82 /// Rationale: 83 /// Primary references are never unified. This is because: 84 /// (a) The user expects that a primary reference will be respected. 85 /// (b) When FindDependencies is false and AutoUnify is true, we'd have to find all 86 /// dependencies anyway to make things work consistently. This would be a significant 87 /// perf hit when loading large solutions. 88 /// </summary> 89 [Fact] 90 [Trait("Category", "mono-osx-failing")] ExistsDifferentName()91 public void ExistsDifferentName() 92 { 93 // Create the engine. 94 MockEngine engine = new MockEngine(); 95 96 ITaskItem[] assemblyNames = new TaskItem[] 97 { 98 new TaskItem("UnifyMe, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") 99 }; 100 assemblyNames[0].SetMetadata("SpecificVersion", "true"); 101 102 // Construct the app.config. 103 string appConfigFile = WriteAppConfig 104 ( 105 " <dependentAssembly>\n" + 106 " <assemblyIdentity name='DontUnifyMe' PublicKeyToken='b77a5c561934e089' culture='neutral' />\n" + 107 " <bindingRedirect oldVersion='1.0.0.0' newVersion='2.0.0.0' />\n" + 108 " </dependentAssembly>\n" 109 ); 110 111 // Now, pass feed resolved primary references into ResolveAssemblyReference. 112 ResolveAssemblyReference t = new ResolveAssemblyReference(); 113 114 t.BuildEngine = engine; 115 t.Assemblies = assemblyNames; 116 t.SearchPaths = DefaultPaths; 117 t.AppConfigFile = appConfigFile; 118 119 bool succeeded = Execute(t); 120 121 Assert.True(succeeded); 122 Assert.Equal(1, t.ResolvedFiles.Length); 123 AssertNoCase("UnifyMe, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, ProcessorArchitecture=MSIL", t.ResolvedFiles[0].GetMetadata("FusionName")); 124 125 // Cleanup. 126 File.Delete(appConfigFile); 127 } 128 129 /// <summary> 130 /// In this case, 131 /// - A single primary version-strict reference was passed in to assembly version 1.0.0.0 132 /// - An app.config was passed in that promotes assembly version from range 0.0.0.0-1.5.0.0 to 2.0.0.0 133 /// - Version 1.0.0.0 of the file exists. 134 /// - Version 2.0.0.0 of the file exists. 135 /// Expected: 136 /// -- The resulting assembly returned should be 1.0.0.0. 137 /// Rationale: 138 /// Primary references are never unified. This is because: 139 /// (a) The user expects that a primary reference will be respected. 140 /// (b) When FindDependencies is false and AutoUnify is true, we'd have to find all 141 /// dependencies anyway to make things work consistently. This would be a significant 142 /// perf hit when loading large solutions. 143 /// </summary> 144 [Fact] 145 [Trait("Category", "mono-osx-failing")] ExistsOldVersionRange()146 public void ExistsOldVersionRange() 147 { 148 // Create the engine. 149 MockEngine engine = new MockEngine(); 150 151 ITaskItem[] assemblyNames = new TaskItem[] 152 { 153 new TaskItem("UnifyMe, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") 154 }; 155 assemblyNames[0].SetMetadata("SpecificVersion", "true"); 156 157 // Construct the app.config. 158 string appConfigFile = WriteAppConfig 159 ( 160 " <dependentAssembly>\n" + 161 " <assemblyIdentity name='UnifyMe' PublicKeyToken='b77a5c561934e089' culture='neutral' />\n" + 162 " <bindingRedirect oldVersion='0.0.0.0-1.5.0.0' newVersion='2.0.0.0' />\n" + 163 " </dependentAssembly>\n" 164 ); 165 166 // Now, pass feed resolved primary references into ResolveAssemblyReference. 167 ResolveAssemblyReference t = new ResolveAssemblyReference(); 168 169 t.BuildEngine = engine; 170 t.Assemblies = assemblyNames; 171 t.SearchPaths = DefaultPaths; 172 t.AppConfigFile = appConfigFile; 173 174 bool succeeded = Execute(t); 175 176 Assert.True(succeeded); 177 Assert.Equal(1, t.ResolvedFiles.Length); 178 AssertNoCase("UnifyMe, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, ProcessorArchitecture=MSIL", t.ResolvedFiles[0].GetMetadata("FusionName")); 179 180 // Cleanup. 181 File.Delete(appConfigFile); 182 } 183 184 /// <summary> 185 /// In this case, 186 /// - A single primary version-strict reference was passed in to assembly version 1.0.0.0 187 /// - An app.config was passed in that promotes assembly version from 1.0.0.0 to 4.0.0.0 188 /// - Version 1.0.0.0 of the file exists. 189 /// - Version 4.0.0.0 of the file *does not* exist. 190 /// Expected: 191 /// -- The resulting assembly returned should be 1.0.0.0. 192 /// Rationale: 193 /// Primary references are never unified. This is because: 194 /// (a) The user expects that a primary reference will be respected. 195 /// (b) When FindDependencies is false and AutoUnify is true, we'd have to find all 196 /// dependencies anyway to make things work consistently. This would be a significant 197 /// perf hit when loading large solutions. 198 /// </summary> 199 [Fact] 200 [Trait("Category", "mono-osx-failing")] HighVersionDoesntExist()201 public void HighVersionDoesntExist() 202 { 203 // Create the engine. 204 MockEngine engine = new MockEngine(); 205 206 ITaskItem[] assemblyNames = new TaskItem[] 207 { 208 new TaskItem("UnifyMe, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") 209 }; 210 assemblyNames[0].SetMetadata("SpecificVersion", "true"); 211 212 // Construct the app.config. 213 string appConfigFile = WriteAppConfig 214 ( 215 " <dependentAssembly>\n" + 216 " <assemblyIdentity name='UnifyMe' PublicKeyToken='b77a5c561934e089' culture='neutral' />\n" + 217 " <bindingRedirect oldVersion='1.0.0.0' newVersion='4.0.0.0' />\n" + 218 " </dependentAssembly>\n" 219 ); 220 221 // Now, pass feed resolved primary references into ResolveAssemblyReference. 222 ResolveAssemblyReference t = new ResolveAssemblyReference(); 223 224 t.BuildEngine = engine; 225 t.Assemblies = assemblyNames; 226 t.SearchPaths = DefaultPaths; 227 t.AppConfigFile = appConfigFile; 228 229 bool succeeded = Execute(t); 230 231 Assert.True(succeeded); 232 Assert.Equal(1, t.ResolvedFiles.Length); 233 AssertNoCase("UnifyMe, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, ProcessorArchitecture=MSIL", t.ResolvedFiles[0].GetMetadata("FusionName")); 234 235 // Cleanup. 236 File.Delete(appConfigFile); 237 } 238 239 /// <summary> 240 /// In this case, 241 /// - A single primary version-strict reference was passed in to assembly version 0.5.0.0 242 /// - An app.config was passed in that promotes assembly version from 0.0.0.0-2.0.0.0 to 2.0.0.0 243 /// - Version 0.5.0.0 of the file *does not* exists. 244 /// - Version 2.0.0.0 of the file exists. 245 /// Expected: 246 /// - The reference is not resolved. 247 /// Rationale: 248 /// Primary references are never unified--even those that don't exist on disk. This is because: 249 /// (a) The user expects that a primary reference will be respected. 250 /// (b) When FindDependencies is false and AutoUnify is true, we'd have to find all 251 /// dependencies anyway to make things work consistently. This would be a significant 252 /// perf hit when loading large solutions. 253 /// </summary> 254 [Fact] LowVersionDoesntExist()255 public void LowVersionDoesntExist() 256 { 257 // Create the engine. 258 MockEngine engine = new MockEngine(); 259 260 ITaskItem[] assemblyNames = new TaskItem[] 261 { 262 new TaskItem("UnifyMe, Version=0.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") 263 }; 264 assemblyNames[0].SetMetadata("SpecificVersion", "true"); 265 266 // Construct the app.config. 267 string appConfigFile = WriteAppConfig 268 ( 269 " <dependentAssembly>\n" + 270 " <assemblyIdentity name='UnifyMe' PublicKeyToken='b77a5c561934e089' culture='neutral' />\n" + 271 " <bindingRedirect oldVersion='0.0.0.0-2.0.0.0' newVersion='2.0.0.0' />\n" + 272 " </dependentAssembly>\n" 273 ); 274 275 // Now, pass feed resolved primary references into ResolveAssemblyReference. 276 ResolveAssemblyReference t = new ResolveAssemblyReference(); 277 278 t.BuildEngine = engine; 279 t.Assemblies = assemblyNames; 280 t.SearchPaths = DefaultPaths; 281 t.AppConfigFile = appConfigFile; 282 283 bool succeeded = Execute(t); 284 285 Assert.True(succeeded); 286 Assert.Equal(0, t.ResolvedFiles.Length); 287 288 // Cleanup. 289 File.Delete(appConfigFile); 290 } 291 } 292 }