/// <summary> /// Returns a unique directory for the specific resource /// </summary> public static string GetResourceSpecificDir(string baseDir, Plugin plugin) { // Format is: [base]\[plugin.version]\[resource name] string pluginDir = GetPluginSpecificDir(baseDir, plugin); string resourceFolder = StripInvalidDirectoryChars(plugin.StaticResourceName); string fullDir = Path.Combine(pluginDir, resourceFolder); return fullDir; }
public void EmbeddedInstall_CachingScenarios() { // Arrange string localCacheDir = TestUtils.CreateTestSpecificFolder(this.TestContext); TestLogger logger = new TestLogger(); Plugin requestA = new Plugin("p111", "1.0-SNAPSHOT", "p1.zip"); Plugin requestB = new Plugin("p222", "9.1.3.0", "p2.zip"); MockSonarQubeServer mockServer = new MockSonarQubeServer(); AddPlugin(mockServer, requestA, "aaa", "bbb"); AddPlugin(mockServer, requestB, "ccc"); IList<string> expectedPlugin111Paths = CalculateExpectedCachedFilePaths(localCacheDir, requestA, "p1.zip", "aaa", "bbb"); IList<string> expectedPlugin222Paths = CalculateExpectedCachedFilePaths(localCacheDir, requestB, "p2.zip", "ccc"); List<string> allExpectedPaths = new List<string>(expectedPlugin111Paths); allExpectedPaths.AddRange(expectedPlugin222Paths); EmbeddedAnalyzerInstaller testSubject = new EmbeddedAnalyzerInstaller(mockServer, localCacheDir, logger); AssertExpectedFilesInCache(0, localCacheDir); // cache should be empty to start with // 1. Empty cache -> cache miss -> server called IEnumerable<string> actualFiles = testSubject.InstallAssemblies(new Plugin[] { requestA }); mockServer.AssertMethodCalled(DownloadEmbeddedFileMethodName, 1); // should have tried to download AssertExpectedFilesReturned(expectedPlugin111Paths, actualFiles); AssertExpectedFilesExist(expectedPlugin111Paths); AssertExpectedFilesInCache(3, localCacheDir); // only files for the first request should exist // 2. New request + request request -> partial cache miss -> server called only for the new request actualFiles = testSubject.InstallAssemblies(new Plugin[] { requestA, requestB }); mockServer.AssertMethodCalled(DownloadEmbeddedFileMethodName, 2); // new request AssertExpectedFilesReturned(allExpectedPaths, actualFiles); AssertExpectedFilesExist(allExpectedPaths); AssertExpectedFilesInCache(5, localCacheDir); // files for both plugins should exist // 3. Repeat the request -> cache hit -> server not called actualFiles = testSubject.InstallAssemblies(new Plugin[] { requestA, requestB }); mockServer.AssertMethodCalled(DownloadEmbeddedFileMethodName, 2); // call count should not have changed AssertExpectedFilesReturned(allExpectedPaths, actualFiles); // 4. Clear the cache and request both -> cache miss -> multiple requests Directory.Delete(localCacheDir, true); Assert.IsFalse(Directory.Exists(localCacheDir), "Test error: failed to delete the local cache directory"); actualFiles = testSubject.InstallAssemblies(new Plugin[] { requestA, requestB }); mockServer.AssertMethodCalled(DownloadEmbeddedFileMethodName, 4); // two new requests AssertExpectedFilesReturned(allExpectedPaths, actualFiles); AssertExpectedFilesExist(allExpectedPaths); AssertExpectedFilesInCache(5, localCacheDir); // files for both plugins should exist }
private IEnumerable<string> GetPluginResourceFiles(Plugin plugin) { this.logger.LogDebug(RoslynResources.EAI_ProcessingPlugin, plugin.Key, plugin.Version); string cacheDir = GetResourceSpecificDir(this.localCacheDirectory, plugin); IEnumerable<string> allFiles = FetchFilesFromCache(cacheDir); if (allFiles.Any()) { this.logger.LogDebug(RoslynResources.EAI_CacheHit, cacheDir); } else { this.logger.LogDebug(RoslynResources.EAI_CacheMiss); if (FetchResourceFromServer(plugin, cacheDir)) { allFiles = FetchFilesFromCache(cacheDir); Debug.Assert(allFiles.Any(), "Expecting to find files in cache after successful fetch from server"); } } return allFiles; }
private bool FetchResourceFromServer(Plugin plugin, string targetDir) { this.logger.LogDebug(RoslynResources.EAI_FetchingPluginResource, plugin.Key, plugin.Version, plugin.StaticResourceName); Directory.CreateDirectory(targetDir); bool success = server.TryDownloadEmbeddedFile(plugin.Key, plugin.StaticResourceName, targetDir); if (success) { string targetFilePath = Path.Combine(targetDir, plugin.StaticResourceName); if (IsZipFile(targetFilePath)) { this.logger.LogDebug(Resources.MSG_ExtractingFiles, targetDir); ZipFile.ExtractToDirectory(targetFilePath, targetDir); } } else { this.logger.LogWarning(RoslynResources.EAI_PluginResourceNotFound, plugin.Key, plugin.Version, plugin.StaticResourceName); } return success; }
/// <summary> /// Returns a version-specific directory in which the plugin resources /// will be cached /// </summary> private static string GetPluginSpecificDir(string baseDir, Plugin plugin) { // Format is: [base]\[plugin_version] string pluginVersionFolder = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}_{1}", plugin.Key, plugin.Version); pluginVersionFolder = StripInvalidDirectoryChars(pluginVersionFolder); string fullDir = Path.Combine(baseDir, pluginVersionFolder); return fullDir; }
private void AddPlugin(MockSonarQubeServer mockServer, Plugin plugin, params string[] files) { mockServer.Data.InstalledPlugins.Add(plugin.Key); mockServer.Data.AddEmbeddedZipFile(plugin.Key, plugin.StaticResourceName, files); }
private static IList<string> CalculateExpectedCachedFilePaths(string baseDir, Plugin plugin, params string[] fileNames) { List<string> files = new List<string>(); string pluginDir = EmbeddedAnalyzerInstaller.GetResourceSpecificDir(baseDir, plugin); foreach (string fileName in fileNames) { string fullFilePath = Path.Combine(pluginDir, fileName); files.Add(fullFilePath); } return files; }
public void EmbeddedInstall_SinglePlugin_SingleResource_Succeeds() { // Arrange string localCacheDir = TestUtils.CreateTestSpecificFolder(this.TestContext); TestLogger logger = new TestLogger(); Plugin requestedPlugin = new Plugin("plugin1", "1.0", "embeddedFile1.zip"); MockSonarQubeServer mockServer = new MockSonarQubeServer(); AddPlugin(mockServer, requestedPlugin, "file1.dll", "file2.txt"); IList<string> expectedFilePaths = CalculateExpectedCachedFilePaths(localCacheDir, requestedPlugin, "embeddedFile1.zip", "file1.dll", "file2.txt"); EmbeddedAnalyzerInstaller testSubject = new EmbeddedAnalyzerInstaller(mockServer, localCacheDir, logger); // Act IEnumerable<string> actualFiles = testSubject.InstallAssemblies(new Plugin[] { requestedPlugin }); // Assert Assert.IsNotNull(actualFiles, "Returned list should not be null"); AssertExpectedFilesReturned(expectedFilePaths, actualFiles); AssertExpectedFilesExist(expectedFilePaths); AssertExpectedFilesInCache(3, localCacheDir); // one zip containing two files }
public void EmbeddedInstall_MultiplePlugins_Succeeds() { // Arrange string localCacheDir = TestUtils.CreateTestSpecificFolder(this.TestContext); TestLogger logger = new TestLogger(); Plugin request1 = new Plugin("no.matching.resource.plugin", "2.0", "non.existent.resource.zip"); Plugin request2 = new Plugin("plugin1", "1.0", "p1.resource1.zip"); Plugin request3 = new Plugin("plugin1", "1.0", "p1.resource2.zip"); // second resource for plugin 1 Plugin request4 = new Plugin("plugin2", "2.0", "p2.resource1.zip"); MockSonarQubeServer mockServer = new MockSonarQubeServer(); AddPlugin(mockServer, request2, "p1.resource1.file1.dll", "p1.resource1.file2.dll"); AddPlugin(mockServer, request3, "p1.resource2.file1.dll"); AddPlugin(mockServer, request4, "p2.resource1.dll"); List<string> expectedPaths = new List<string>(); expectedPaths.AddRange(CalculateExpectedCachedFilePaths(localCacheDir, request2, "p1.resource1.zip", "p1.resource1.file1.dll", "p1.resource1.file2.dll")); expectedPaths.AddRange(CalculateExpectedCachedFilePaths(localCacheDir, request3, "p1.resource2.zip", "p1.resource2.file1.dll")); expectedPaths.AddRange(CalculateExpectedCachedFilePaths(localCacheDir, request4, "p2.resource1.zip", "p2.resource1.dll")); EmbeddedAnalyzerInstaller testSubject = new EmbeddedAnalyzerInstaller(mockServer, localCacheDir, logger); // Act IEnumerable<string> actualFiles = testSubject.InstallAssemblies(new Plugin[] { request1, request2, request3, request4}); // Assert Assert.IsNotNull(actualFiles, "Returned list should not be null"); AssertExpectedFilesReturned(expectedPaths, actualFiles); AssertExpectedFilesExist(expectedPaths); AssertExpectedFilesInCache(expectedPaths.Count, localCacheDir); }
public void EmbeddedInstall_MissingResource_SucceedsWithWarningAndNoFiles() { // Arrange string localCacheDir = TestUtils.CreateTestSpecificFolder(this.TestContext); TestLogger logger = new TestLogger(); MockSonarQubeServer mockServer = CreateServerWithDummyPlugin("plugin1"); Plugin requestedPlugin = new Plugin() { Key = "missingPlugin", Version = "1.0", StaticResourceName = "could.be.anything" }; EmbeddedAnalyzerInstaller testSubject = new EmbeddedAnalyzerInstaller(mockServer, localCacheDir, logger); // Act IEnumerable<string> actualFiles = testSubject.InstallAssemblies(new Plugin[] { requestedPlugin }); // Assert Assert.IsNotNull(actualFiles, "Returned list should not be null"); AssertExpectedFilesReturned(Enumerable.Empty<string>(), actualFiles); AssertExpectedFilesInCache(0, localCacheDir); logger.AssertWarningsLogged(1); }
public void EmbeddedInstall_EmptyCacheDirectoryExists_CacheMissAndServerCalled() { // Arrange string localCacheDir = TestUtils.CreateTestSpecificFolder(this.TestContext); TestLogger logger = new TestLogger(); Plugin requestA = new Plugin("p111", "1.0-SNAPSHOT", "p1.zip"); MockSonarQubeServer mockServer = new MockSonarQubeServer(); AddPlugin(mockServer, requestA, "aaa.txt"); IList<string> expectedPlugin111Paths = CalculateExpectedCachedFilePaths(localCacheDir, requestA, "p1.zip", "aaa.txt"); Assert.AreNotEqual(0, expectedPlugin111Paths.Count, "Test setup error: expecting at least one file path"); // Create the expected directories, but not the files foreach(string file in expectedPlugin111Paths) { string dir = Path.GetDirectoryName(file); Directory.CreateDirectory(dir); } AssertExpectedFilesInCache(0, localCacheDir); // cache should be empty to start with Assert.AreNotEqual(0, Directory.GetDirectories(localCacheDir, "*.*", SearchOption.AllDirectories)); // ... but should have directories EmbeddedAnalyzerInstaller testSubject = new EmbeddedAnalyzerInstaller(mockServer, localCacheDir, logger); // 1. Empty directory = cache miss -> server called IEnumerable<string> actualFiles = testSubject.InstallAssemblies(new Plugin[] { requestA }); mockServer.AssertMethodCalled(DownloadEmbeddedFileMethodName, 1); // should have tried to download AssertExpectedFilesReturned(expectedPlugin111Paths, actualFiles); AssertExpectedFilesExist(expectedPlugin111Paths); AssertExpectedFilesInCache(2, localCacheDir); }