async Task <RazorCSharpParsedDocument> Parse(string text, bool isPreprocessed) { var project = Services.ProjectService.CreateDotNetProject("C#", "AspNetApp"); project.FileName = UnitTests.TestBase.GetTempFile(".csproj"); string file = UnitTests.TestBase.GetTempFile(".cshtml"); ProjectFile projectFile = project.AddFile(file); if (isPreprocessed) { projectFile.Generator = "RazorTemplatePreprocessor"; } var sev = new TestViewContent(); sev.Project = project; sev.ContentName = file; sev.Text = text; var tww = new TestWorkbenchWindow(); tww.ViewContent = sev; var doc = new TestDocument(tww); doc.Editor.FileName = sev.ContentName; doc.UpdateProject(project); solution = new MonoDevelop.Projects.Solution(); solution.DefaultSolutionFolder.AddItem(project); solution.AddConfiguration("", true); await TypeSystemServiceTestExtensions.LoadSolution(solution); var parser = new RazorTestingParser { Doc = doc }; var options = new ParseOptions { Project = project, FileName = file, Content = new StringTextSource(text) }; return((RazorCSharpParsedDocument)parser.Parse(options, default(CancellationToken)).Result); }
public async Task CSharpFile_BuildActionNone_FileNotUsed() { FilePath solFile = Util.GetSampleProject("build-action-none", "build-action-none.sln"); using (var sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile)) using (var ws = await TypeSystemServiceTestExtensions.LoadSolution(sol)) { try { var projects = ws.CurrentSolution.Projects.ToArray(); var project = projects.Single(); // Check that build action none .cs file is not used by the type system. Assert.IsFalse(project.Documents.Any(d => d.Name == "DoNotCompile.cs")); Assert.IsTrue(project.Documents.Any(d => d.Name == "Program.cs")); } finally { TypeSystemServiceTestExtensions.UnloadSolution(sol); } } }
public async Task MultiTargetFramework_ProjectReferences() { FilePath solFile = Util.GetSampleProject("multi-target-project-ref", "multi-target.sln"); CreateNuGetConfigFile(solFile.ParentDirectory); Util.RunMSBuild($"/t:Restore /p:RestoreDisableParallel=true \"{solFile}\""); using (var sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile)) using (var ws = await TypeSystemServiceTestExtensions.LoadSolution(sol)) { try { var projectIds = ws.CurrentSolution.ProjectIds.ToArray(); var projects = ws.CurrentSolution.Projects.ToArray(); var netframeworkProject = projects.FirstOrDefault(p => p.Name == "multi-target (net471)"); var netstandardProject = projects.FirstOrDefault(p => p.Name == "multi-target (netstandard1.0)"); var netframeworkProjectRef = projects.FirstOrDefault(p => p.Name == "multi-target-ref (net472)"); var netstandardProjectRef = projects.FirstOrDefault(p => p.Name == "multi-target-ref (netstandard1.4)"); // Should be four projects - one for each target framework. Assert.AreEqual(4, projectIds.Length); Assert.AreEqual(4, projects.Length); Assert.IsNotNull(netframeworkProject); Assert.IsNotNull(netstandardProject); Assert.IsNotNull(netframeworkProjectRef); Assert.IsNotNull(netstandardProjectRef); // Check project references. var projectReferences = netstandardProjectRef.ProjectReferences.ToArray(); Assert.AreEqual(1, projectReferences.Length); Assert.AreEqual(netstandardProject.Id, projectReferences [0].ProjectId); projectReferences = netframeworkProjectRef.ProjectReferences.ToArray(); Assert.AreEqual(1, projectReferences.Length); Assert.AreEqual(netframeworkProject.Id, projectReferences [0].ProjectId); } finally { TypeSystemServiceTestExtensions.UnloadSolution(sol); } } }
public async Task ReferenceCacheWorks() { string solFile = Util.GetSampleProject("console-project", "ConsoleProject.sln"); using (var sol = (MonoDevelop.Projects.Solution) await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile)) using (var ws = await TypeSystemServiceTestExtensions.LoadSolution(sol)) { try { var manager = ws.MetadataReferenceManager; var cache = new MonoDevelopMetadataReferenceManager.MetadataReferenceCache(); // Create one with default assembly properties var asm = typeof(MonoDevelopMetadataReferenceManagerMetadataReferenceCacheTests).Assembly.Location; var item = cache.GetOrCreate(manager, asm, MetadataReferenceProperties.Assembly); Assert.IsNotNull(item); var item2 = cache.GetOrCreate(manager, asm, MetadataReferenceProperties.Assembly); Assert.AreSame(item, item2, "Item that is in cache should be returned"); // Create one with custom properties var item3 = cache.GetOrCreate(manager, asm, MetadataReferenceProperties.Assembly.WithAliases(new [] { "a" })); Assert.IsNotNull(item3); var item4 = cache.GetOrCreate(manager, asm, MetadataReferenceProperties.Assembly.WithAliases(new [] { "a" })); Assert.AreSame(item3, item4, "Item that is in cache should be returned"); // Clear the cache, new items should be returned from now on. cache.ClearCache(); var item5 = cache.GetOrCreate(manager, asm, MetadataReferenceProperties.Assembly); Assert.IsNotNull(item5); Assert.AreNotSame(item, item5, "Cache was cleared, so new item should be returned"); var item6 = cache.GetOrCreate(manager, asm, MetadataReferenceProperties.Assembly.WithAliases(new [] { "a" })); Assert.AreNotSame(item3, item6, "Cache was cleared, so new item should be returned"); cache.ClearCache(); } finally { TypeSystemServiceTestExtensions.UnloadSolution(sol); } } }
public async Task SymlinkedFilesHaveProperdocumentRegistration() { if (Platform.IsWindows) { Assert.Ignore("Symlinks not supported on Windows"); } FilePath solFile = Util.GetSampleProjectPath("symlinked-source-file", "test-symlinked-file", "test-symlinked-file.sln"); var solutionDirectory = Path.GetDirectoryName(solFile); var dataFile = Path.Combine(solutionDirectory, "SymlinkedFileData.txt"); var data = File.ReadAllLines(dataFile); var symlinkFileName = Path.Combine(solutionDirectory, data [0]); var symlinkFileSource = Path.GetFullPath(Path.Combine(solutionDirectory, data [1])); File.Delete(symlinkFileName); Process.Start(new ProcessStartInfo("ln", $"-s '{symlinkFileSource}' '{symlinkFileName}'") { UseShellExecute = false, }).WaitForExit(); using (var sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile)) using (var ws = await TypeSystemServiceTestExtensions.LoadSolution(sol)) { try { var project = sol.GetAllProjects().Single(); foreach (var file in project.Files) { Assert.IsNotNull(IdeApp.TypeSystemService.GetDocumentId(project, file.FilePath.ResolveLinks())); if (file.FilePath.FileName.EndsWith("SymlinkedFile.cs", StringComparison.Ordinal)) { Assert.IsNull(IdeServices.TypeSystemService.GetDocumentId(project, file.FilePath)); } } } finally { TypeSystemServiceTestExtensions.UnloadSolution(sol); } } }
public async Task EditorConfigFile_ModifiedExternally() { FilePath solFile = Util.GetSampleProject("additional-files", "additional-files.sln"); using (var sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile)) using (var ws = await TypeSystemServiceTestExtensions.LoadSolution(sol)) { try { var project = sol.GetAllProjects().Single(); FilePath editorConfigFileName = solFile.ParentDirectory.Combine(".editorconfig"); var projectInfo = ws.CurrentSolution.Projects.Single(); var editorConfigDoc = projectInfo.AnalyzerConfigDocuments.Single(d => d.FilePath == editorConfigFileName); bool analyzerConfigDocumentChanged = false; ws.WorkspaceChanged += (sender, e) => { if (e.DocumentId == editorConfigDoc.Id && e.Kind == Microsoft.CodeAnalysis.WorkspaceChangeKind.AnalyzerConfigDocumentChanged) { analyzerConfigDocumentChanged = true; } }; // Add error style to .editorconfig string contents = "root = true\r\n" + "\r\n" + "[*.cs]\r\n" + "csharp_style_var_for_built_in_types = true:error\r\n"; File.WriteAllText(editorConfigFileName, contents); FileService.NotifyFileChanged(editorConfigFileName); Func <bool> action = () => analyzerConfigDocumentChanged; await AssertIsTrueWithTimeout(action, "Timed out waiting for analyzer config file changed event", 10000); } finally { TypeSystemServiceTestExtensions.UnloadSolution(sol); } } }
public async Task MultiTargetFramework_RemoveProject() { FilePath solFile = Util.GetSampleProject("multi-target-netframework", "multi-target.sln"); CreateNuGetConfigFile(solFile.ParentDirectory); Util.RunMSBuild($"/t:Restore /p:RestoreDisableParallel=true \"{solFile}\""); using (var sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile)) using (var ws = await TypeSystemServiceTestExtensions.LoadSolution(sol)) { try { var project = sol.GetAllProjects().Single(); var projectIds = ws.CurrentSolution.ProjectIds.ToArray(); var projects = ws.CurrentSolution.Projects.ToArray(); var netframeworkProject = projects.FirstOrDefault(p => p.Name == "multi-target (net472)"); var netstandardProject = projects.FirstOrDefault(p => p.Name == "multi-target (netstandard1.0)"); // Should be two projects - one for each target framework. Assert.AreEqual(2, projectIds.Length); Assert.AreEqual(2, projects.Length); Assert.IsNotNull(netframeworkProject); Assert.IsNotNull(netstandardProject); sol.RootFolder.Items.Remove(project); await sol.SaveAsync(Util.GetMonitor()); projectIds = ws.CurrentSolution.ProjectIds.ToArray(); projects = ws.CurrentSolution.Projects.ToArray(); Assert.AreEqual(0, projectIds.Length); Assert.AreEqual(0, projects.Length); } finally { TypeSystemServiceTestExtensions.UnloadSolution(sol); } } }
public async Task AdditionalFiles_EditorConfigFiles() { FilePath solFile = Util.GetSampleProject("additional-files", "additional-files.sln"); using (var sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile)) using (var ws = await TypeSystemServiceTestExtensions.LoadSolution(sol)) { try { var project = sol.GetAllProjects().Single(); var projectInfo = ws.CurrentSolution.Projects.Single(); var additionalDocs = projectInfo.AdditionalDocuments.ToArray(); var editorConfigDocs = projectInfo.AnalyzerConfigDocuments.ToArray(); FilePath expectedAdditionalFileName = project.BaseDirectory.Combine("additional-file.txt"); FilePath expectedEditorConfigFileName = solFile.ParentDirectory.Combine(".editorconfig"); Assert.IsTrue(additionalDocs.Any(d => d.FilePath == expectedAdditionalFileName)); Assert.IsTrue(editorConfigDocs.Any(d => d.FilePath == expectedEditorConfigFileName)); } finally { TypeSystemServiceTestExtensions.UnloadSolution(sol); } } }
public async Task ProjectReference() { FilePath solFile = Util.GetSampleProject("netstandard-project", "NetStandardTest.sln"); CreateNuGetConfigFile(solFile.ParentDirectory); Util.RunMSBuild($"/t:Restore /p:RestoreDisableParallel=true \"{solFile}\""); using (var sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile)) using (var ws = await TypeSystemServiceTestExtensions.LoadSolution(sol)) { try { var projects = ws.CurrentSolution.Projects.ToArray(); var netframeworkProject = projects.FirstOrDefault(p => p.Name == "NetStandardTest"); var netstandardProject = projects.FirstOrDefault(p => p.Name == "Lib"); var projectReferences = netframeworkProject.ProjectReferences.ToArray(); Assert.AreEqual(1, projectReferences.Length); Assert.AreEqual(netstandardProject.Id, projectReferences [0].ProjectId); } finally { TypeSystemServiceTestExtensions.UnloadSolution(sol); } } }
public async Task MetadataReferencesToFrameworkAssembliesAreProperlyFound() { if (!IdeApp.IsInitialized) { IdeApp.Initialize(new ProgressMonitor()); } FilePath projFile = Util.GetSampleProject("workspace-metadata-references", "workspace-metadata-references.sln"); using (var sol = (MonoDevelop.Projects.Solution) await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), projFile)) { using (var ws = await TypeSystemServiceTestExtensions.LoadSolution(sol)) { DotNetProject mainProject = null, libraryProject = null, libraryProject461 = null; foreach (var project in sol.GetAllProjects()) { if (project.Name == "workspace-metadata-references") { mainProject = (DotNetProject)project; } else if (project.Name == "library-project") { libraryProject = (DotNetProject)project; } else if (project.Name == "library-project-net461") { libraryProject461 = (DotNetProject)project; } } Assert.IsNotNull(mainProject); Assert.IsNotNull(libraryProject); // Also, add test for net461 to net47. await AddAssemblyReference(ws, libraryProject, mainProject, "System.Messaging"); await AddAssemblyReference(ws, libraryProject461, mainProject, "System.ServiceModel"); } } }
static async Task <EditorInfo> CreateEditor(string text, bool isInCSharpContext) { string parsedText, editorText; int cursorPosition = text.IndexOf('$'); int endPos = text.IndexOf('$', cursorPosition + 1); if (endPos == -1) { parsedText = editorText = text.Substring(0, cursorPosition) + text.Substring(cursorPosition + 1); } else { parsedText = text.Substring(0, cursorPosition) + new string (' ', endPos - cursorPosition) + text.Substring(endPos + 1); editorText = text.Substring(0, cursorPosition) + text.Substring(cursorPosition + 1, endPos - cursorPosition - 1) + text.Substring(endPos + 1); cursorPosition = endPos - 1; } var project = Services.ProjectService.CreateProject("C#", "AspNetApp"); project.FileName = UnitTests.TestBase.GetTempFile(".csproj"); string file = UnitTests.TestBase.GetTempFile(extension); project.AddFile(file); var sev = new TestViewContent(); sev.Project = project; sev.ContentName = file; sev.Text = editorText; sev.CursorPosition = cursorPosition; var tww = new TestWorkbenchWindow(); tww.ViewContent = sev; var doc = new TestDocument(tww); doc.Editor.FileName = sev.ContentName; doc.UpdateProject(project); solution = new MonoDevelop.Projects.Solution(); solution.DefaultSolutionFolder.AddItem(project); solution.AddConfiguration("", true); await TypeSystemServiceTestExtensions.LoadSolution(solution); var parser = new RazorTestingParser { Doc = doc }; var options = new ParseOptions { Project = project, FileName = sev.ContentName, Content = new StringTextSource(parsedText) }; var parsedDoc = await parser.Parse(options, default(CancellationToken)) as RazorCSharpParsedDocument; doc.HiddenParsedDocument = parsedDoc; var editorExtension = new RazorCSharpEditorExtension(doc, parsedDoc as RazorCSharpParsedDocument, isInCSharpContext); return(new EditorInfo { Extension = editorExtension, EditorText = editorText, View = sev }); }
public async Task MultiTargetFramework() { FilePath solFile = Util.GetSampleProject("multi-target-netframework", "multi-target.sln"); CreateNuGetConfigFile(solFile.ParentDirectory); Util.RunMSBuild($"/t:Restore /p:RestoreDisableParallel=true \"{solFile}\""); using (var sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile)) using (var ws = await TypeSystemServiceTestExtensions.LoadSolution(sol)) { try { var project = sol.GetAllProjects().Single(); var projectIds = ws.CurrentSolution.ProjectIds.ToArray(); var projects = ws.CurrentSolution.Projects.ToArray(); var netframeworkProject = projects.FirstOrDefault(p => p.Name == "multi-target (net472)"); var netstandardProject = projects.FirstOrDefault(p => p.Name == "multi-target (netstandard1.0)"); // Should be two projects - one for each target framework. Assert.AreEqual(2, projectIds.Length); Assert.AreEqual(2, projects.Length); Assert.IsNotNull(netframeworkProject); Assert.IsNotNull(netstandardProject); // Check references. var mscorlibNetFramework = netframeworkProject.MetadataReferences .OfType <Microsoft.CodeAnalysis.PortableExecutableReference> () .FirstOrDefault(r => Path.GetFileName(r.FilePath) == "mscorlib.dll"); var systemCollectionsNetFramework = netframeworkProject.MetadataReferences .OfType <Microsoft.CodeAnalysis.PortableExecutableReference> () .FirstOrDefault(r => Path.GetFileName(r.FilePath) == "System.Collections.dll"); var mscorlibNetStandard = netstandardProject.MetadataReferences .OfType <Microsoft.CodeAnalysis.PortableExecutableReference> () .FirstOrDefault(r => Path.GetFileName(r.FilePath) == "mscorlib.dll"); var systemCollectionsNetStandard = netstandardProject.MetadataReferences .OfType <Microsoft.CodeAnalysis.PortableExecutableReference> () .FirstOrDefault(r => Path.GetFileName(r.FilePath) == "System.Collections.dll"); Assert.AreNotEqual(netframeworkProject.MetadataReferences.Count, netstandardProject.MetadataReferences.Count); Assert.IsNotNull(mscorlibNetFramework); Assert.IsNull(mscorlibNetStandard); Assert.IsNull(systemCollectionsNetFramework); Assert.IsNotNull(systemCollectionsNetStandard); // Check source files are correct for each framework. Assert.IsFalse(netframeworkProject.Documents.Any(d => d.Name == "MyClass-netstandard.cs")); Assert.IsTrue(netframeworkProject.Documents.Any(d => d.Name == "MyClass-netframework.cs")); Assert.IsTrue(netstandardProject.Documents.Any(d => d.Name == "MyClass-netstandard.cs")); Assert.IsFalse(netstandardProject.Documents.Any(d => d.Name == "MyClass-netframework.cs")); // Check compiler parameter information Assert.That(netframeworkProject.ParseOptions.PreprocessorSymbolNames, Contains.Item("NET472")); Assert.That(netstandardProject.ParseOptions.PreprocessorSymbolNames, Contains.Item("NETSTANDARD1_0")); Assert.That(netframeworkProject.CompilationOptions.SpecificDiagnosticOptions.Keys, Contains.Item("NET12345")); Assert.IsFalse(netframeworkProject.CompilationOptions.SpecificDiagnosticOptions.Keys.Contains("STA4433")); Assert.That(netstandardProject.CompilationOptions.SpecificDiagnosticOptions.Keys, Contains.Item("STA4433")); Assert.IsFalse(netstandardProject.CompilationOptions.SpecificDiagnosticOptions.Keys.Contains("NET12345")); // Ensure that facade assemblies are not added to the .NET Standard project. This would happen // if the .NET Framework was the first target framework listed in TargetFrameworks. The Project // would see a .NET Standard assembly was referenced and add the facade assemblies. var facadeFound = netstandardProject.MetadataReferences .OfType <Microsoft.CodeAnalysis.PortableExecutableReference> () .Where(r => r.FilePath.IndexOf("Facades", StringComparison.OrdinalIgnoreCase) >= 0) .Select(r => r.FilePath) .FirstOrDefault(); Assert.IsNull(facadeFound); } finally { TypeSystemServiceTestExtensions.UnloadSolution(sol); } } }
public async Task SingleTargetFramework_ReloadProjectAfterChangingToMultiTargetFramework_TypeSystemRespondsToProjectModifiedEvents() { FilePath solFile = Util.GetSampleProject("multi-target-reload", "multi-target-reload.sln"); CreateNuGetConfigFile(solFile.ParentDirectory); Util.RunMSBuild($"/t:Restore /p:RestoreDisableParallel=true \"{solFile}\""); using (var sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile)) using (var ws = await TypeSystemServiceTestExtensions.LoadSolution(sol)) { try { var project = sol.GetAllProjects().Single(); var projectIds = ws.CurrentSolution.ProjectIds.ToArray(); var projects = ws.CurrentSolution.Projects.ToArray(); // Should be one Roslyn project. Assert.AreEqual(1, projectIds.Length); Assert.AreEqual(1, projects.Length); var updatedProjectFileName = project.FileName.ChangeName("multi-target-reload"); string xml = File.ReadAllText(updatedProjectFileName); File.WriteAllText(project.FileName, xml); var reloadedProject = (DotNetProject)await sol.RootFolder.ReloadItem(Util.GetMonitor(), project); // Try a few times since the type system needs time to reload const int timeout = 10000; // ms int howLong = 0; const int interval = 200; // ms while (true) { var newProjectIds = ws.CurrentSolution.ProjectIds.ToArray(); projects = ws.CurrentSolution.Projects.ToArray(); var netstandardProject = projects.FirstOrDefault(p => p.Name == "netstandard (netstandard2.0)"); var netframeworkProject = projects.FirstOrDefault(p => p.Name == "netstandard (net462)"); if (netframeworkProject != null && netstandardProject != null) { Assert.AreEqual(2, newProjectIds.Length); Assert.AreEqual(2, projects.Length); break; } if (howLong >= timeout) { Assert.Fail("Timed out waiting for type system information to be updated."); } await Task.Delay(interval); howLong += interval; } // Add a new file. var projectFileName = reloadedProject.BaseDirectory.Combine("Test.cs"); File.WriteAllText(projectFileName, "class Test { }"); var projectFile = new ProjectFile(projectFileName, BuildAction.Compile); reloadedProject.Files.Add(projectFile); howLong = 0; while (true) { projects = ws.CurrentSolution.Projects.ToArray(); var netstandardProject = projects.FirstOrDefault(p => p.Name == "netstandard (netstandard2.0)"); var netframeworkProject = projects.FirstOrDefault(p => p.Name == "netstandard (net462)"); if (netstandardProject.Documents.Any(d => d.Name == "Test.cs") && netframeworkProject.Documents.Any(d => d.Name == "Test.cs")) { // OK - document registered with type system service. return; } if (howLong >= timeout) { Assert.Fail("Timed out waiting for type system information to be updated after adding file."); } await Task.Delay(interval); howLong += interval; } } finally { TypeSystemServiceTestExtensions.UnloadSolution(sol); } } }
public async Task MultiTargetFramework_ReloadProject_TargetFrameworksChanged() { FilePath solFile = Util.GetSampleProject("multi-target", "multi-target.sln"); CreateNuGetConfigFile(solFile.ParentDirectory); Util.RunMSBuild($"/t:Restore /p:RestoreDisableParallel=true \"{solFile}\""); using (var sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile)) using (var ws = await TypeSystemServiceTestExtensions.LoadSolution(sol)) { try { var project = sol.GetAllProjects().Single(); var projectIds = ws.CurrentSolution.ProjectIds.ToArray(); var projects = ws.CurrentSolution.Projects.ToArray(); var netcoreProject = projects.FirstOrDefault(p => p.Name == "multi-target (netcoreapp1.1)"); var netstandardProject = projects.FirstOrDefault(p => p.Name == "multi-target (netstandard1.0)"); // Should be two projects - one for each target framework. Assert.AreEqual(2, projectIds.Length); Assert.AreEqual(2, projects.Length); Assert.IsNotNull(netcoreProject); Assert.IsNotNull(netstandardProject); var updatedProjectFileName = project.FileName.ChangeName("multi-target-reload"); string xml = File.ReadAllText(updatedProjectFileName); File.WriteAllText(project.FileName, xml); await sol.RootFolder.ReloadItem(Util.GetMonitor(), project); // Try a few times since the type system needs time to reload const int timeout = 10000; // ms int howLong = 0; const int interval = 200; // ms while (true) { var newProjectIds = ws.CurrentSolution.ProjectIds.ToArray(); projects = ws.CurrentSolution.Projects.ToArray(); netcoreProject = projects.FirstOrDefault(p => p.Name == "multi-target (netcoreapp1.2)"); netstandardProject = projects.FirstOrDefault(p => p.Name == "multi-target (netstandard1.3)"); if (netcoreProject != null && netstandardProject != null) { Assert.AreEqual(2, newProjectIds.Length); Assert.AreEqual(2, projects.Length); return; } if (howLong >= timeout) { Assert.Fail("Timed out waiting for type system information to be updated."); } await Task.Delay(interval); howLong += interval; } } finally { TypeSystemServiceTestExtensions.UnloadSolution(sol); } } }
public async Task ReferenceCacheSnapshotUpdates() { string solFile = Util.GetSampleProject("console-project", "ConsoleProject.sln"); var tempPath = Path.GetFullPath(Path.GetTempFileName()); var oldAsm = typeof(MonoDevelopMetadataReferenceManagerTests).Assembly.Location; File.Copy(oldAsm, tempPath, true); try { using (var sol = (MonoDevelop.Projects.Solution) await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile)) using (var ws = await TypeSystemServiceTestExtensions.LoadSolution(sol)) { await FileWatcherService.Add(sol); var manager = ws.MetadataReferenceManager; var item = manager.GetOrCreateMetadataReference(tempPath, MetadataReferenceProperties.Assembly); Assert.IsNotNull(item); await FileWatcherService.Update(); var initialId = item.CurrentSnapshot.GetMetadataId(); var taskForNewAsm = WaitForSnapshotChange(item); // Replace the assembly with another one. var newAsm = typeof(MonoDevelopMetadataReference).Assembly.Location; File.Copy(newAsm, tempPath, true); var argsForNewAsm = await taskForNewAsm; Assert.AreSame(item.CurrentSnapshot, argsForNewAsm.OldSnapshot); Assert.AreNotSame(argsForNewAsm.OldSnapshot, argsForNewAsm.NewSnapshot.Value); // item.CurrentSnapshot is now updated Assert.AreNotEqual(initialId, item.CurrentSnapshot.GetMetadataId()); var taskForOldAsm = WaitForSnapshotChange(item); File.Copy(newAsm, tempPath, true); var argsForOldAsm = await taskForOldAsm; Assert.AreSame(item.CurrentSnapshot, argsForOldAsm.OldSnapshot); Assert.AreNotSame(argsForNewAsm.OldSnapshot, argsForNewAsm.NewSnapshot.Value); // Even though the old assembly was put back, it has a new id this time. Assert.AreNotEqual(initialId, item.CurrentSnapshot.GetMetadataId()); } await FileWatcherService.Update(); // At this point, the metadata reference should be disposed. // Check to see if file updates will trigger a file service noification var tcsShouldTimeout = new TaskCompletionSource <bool> (); var ctsFail = new CancellationTokenSource(); ctsFail.Token.Register(() => tcsShouldTimeout.TrySetResult(true)); Core.FileService.FileChanged += (sender, args) => { foreach (var file in args) { if (file.FileName == tempPath) { tcsShouldTimeout.TrySetResult(false); } } }; ctsFail.CancelAfter(1000 * 5); File.WriteAllText(tempPath, ""); Assert.AreEqual(true, await tcsShouldTimeout.Task); } finally { File.Delete(tempPath); } }