public static async Task RunNoCatch(string testName, Func <ApplicationManager, Task> action) { TestTracer.Trace("Running test - {0}", testName); var appManager = await SitePool.CreateApplicationAsync(); TestTracer.Trace("Using site - {0}", appManager.SiteUrl); var dumpPath = Path.Combine(PathHelper.TestResultsPath, testName, testName + ".zip"); bool succcess = true; try { using (StartLogStream(appManager)) { await action(appManager); } KuduUtils.DownloadDump(appManager.ServiceUrl, dumpPath); } catch (Exception ex) { KuduUtils.DownloadDump(appManager.ServiceUrl, dumpPath); TestTracer.Trace("Run failed with exception\n{0}", ex); succcess = false; _testFailureOccured = true; throw; } finally { SafeTraceDeploymentLogs(appManager); SitePool.ReportTestCompletion(appManager, succcess); } }
public static void Commit(string repositoryPath, string message) { Executable gitExe = GetGitExe(repositoryPath); try { GitExecute(gitExe, "add -A", message); GitExecute(gitExe, "commit -m \"{0}\"", message); } catch (Exception ex) { // Swallow exceptions on commit, since things like changing line endings // show up as an error TestTracer.Trace("Commit failed with {0}", ex); } // Verify that the commit did go thru string lastCommitMessage = GitExecute(gitExe, "log --oneline -1").Item1; if (lastCommitMessage == null || !lastCommitMessage.Contains(message)) { throw new InvalidOperationException(String.Format("Mismatched commit message '{0}' != '{1}'", lastCommitMessage, message)); } }
private static async Task <ApplicationManager> CreateApplicationInternal(int siteIndex) { string applicationName = _sitePrefix + siteIndex; string operationName = "SitePool.CreateApplicationInternal " + applicationName; var context = new KuduTestContext(); var siteManager = GetSiteManager(context); Site site = siteManager.GetSite(applicationName); if (site != null) { TestTracer.Trace("{0} Site already exists at {1}. Reusing site", operationName, site.SiteUrl); var appManager = new ApplicationManager(siteManager, site, applicationName) { SitePoolIndex = siteIndex }; // In site reuse mode, clean out the existing site so we start clean // Enumrate all w3wp processes and make sure to kill any process with an open handle to klr.host.dll foreach (var process in (await appManager.ProcessManager.GetProcessesAsync()).Where(p => p.Name.Equals("w3wp", StringComparison.OrdinalIgnoreCase))) { var extendedProcess = await appManager.ProcessManager.GetProcessAsync(process.Id); if (extendedProcess.OpenFileHandles.Any(h => h.IndexOf("dnx.host.dll", StringComparison.OrdinalIgnoreCase) != -1)) { await appManager.ProcessManager.KillProcessAsync(extendedProcess.Id, throwOnError : false); } } await appManager.RepositoryManager.Delete(deleteWebRoot : true, ignoreErrors : true); // Make sure we start with the correct default file as some tests expect it WriteIndexHtml(appManager); TestTracer.Trace("{0} completed", operationName); return(appManager); } else { TestTracer.Trace("{0} Creating new site", operationName); lock (_createSiteLock) { if (ConfigurationManager.AppSettings["UseNetworkServiceIdentity"] == "true") { var applicationsPath = context.Configuration.ApplicationsPath; if (!Directory.Exists(applicationsPath)) { Directory.CreateDirectory(applicationsPath); var accessRule = new FileSystemAccessRule("NETWORK SERVICE", fileSystemRights: FileSystemRights.Modify | FileSystemRights.Write | FileSystemRights.ReadAndExecute | FileSystemRights.Read | FileSystemRights.ListDirectory, inheritanceFlags: InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, propagationFlags: PropagationFlags.None, type: AccessControlType.Allow); var directoryInfo = new DirectoryInfo(applicationsPath); DirectorySecurity directorySecurity = directoryInfo.GetAccessControl(); directorySecurity.AddAccessRule(accessRule); directoryInfo.SetAccessControl(directorySecurity); } } site = siteManager.CreateSiteAsync(applicationName).Result; } TestTracer.Trace("{0} Created new site at {1}", operationName, site.SiteUrl); return(new ApplicationManager(siteManager, site, applicationName) { SitePoolIndex = siteIndex }); } }
private static string CreateCachedRepo(string source, string commitId, IDictionary <string, string> environments) { string cachedPath = null; if (source.IndexOf("github.com", StringComparison.OrdinalIgnoreCase) != -1) { // If we're allowed to cache the repository, check if it already exists. If not clone it. string repoName = Path.GetFileNameWithoutExtension(source.Split('/').Last()); // repo cached per test class to support test parallel run var context = TestContext.Current; if (context != null) { repoName = GetRepoNamePerContext(context, repoName); } cachedPath = Path.Combine(PathHelper.RepositoryCachePath, repoName); // Check for the actually .git folder, in case some bogus parent exists but is not an actual repo bool alreadyExists = Directory.Exists(Path.Combine(cachedPath, ".git")) && IsGitRepo(cachedPath); Executable gitExe = GetGitExe(cachedPath, environments); if (alreadyExists) { TestTracer.Trace("Using cached copy at location {0}", cachedPath); // Get it into a clean state on the correct commit id try { // If we don't have a specific commit id to go to, use origin/master if (commitId == null) { commitId = "origin/master"; } GitExecute(gitExe, "reset --hard " + commitId); } catch (Exception e) { // Some repos like Drupal don't use a master branch (e.g. default branch is 7.x). In those cases, // simply reset to the HEAD. That won't undo any test commits, but at least it does some cleanup. if (e.Message.Contains("ambiguous argument 'origin/master'")) { GitExecute(gitExe, "reset --hard HEAD"); } else if (e.Message.Contains("unknown revision")) { // If that commit id doesn't exist, try fetching and doing the reset again // The reason we don't initially fetch is to avoid the network hit when not necessary GitExecute(gitExe, "fetch origin"); GitExecute(gitExe, "reset --hard " + commitId); } else { throw; } } GitExecute(gitExe, "clean -dxf"); } else { // Delete any leftover, ignoring errors FileSystemHelpers.DeleteDirectorySafe(cachedPath); TestTracer.Trace("Could not find a cached copy at {0}. Cloning from source {1}.", cachedPath, source); PathHelper.EnsureDirectory(cachedPath); GitExecute(gitExe, "clone \"{0}\" .", source); // If we have a commit id, reset to it in case it's older than the latest on our clone if (commitId != null) { GitExecute(gitExe, "reset --hard " + commitId); } } } return(cachedPath); }
private static void OnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) { TestTracer.Trace("OnUnobservedTaskException - {0}", e.Exception.GetBaseException()); e.SetObserved(); }
public static async Task <HttpResponseMessage> WaitForSiteAsync(string siteUrl, ICredentials credentials = null, int retries = 5, int delayBeforeFirstTry = 0, int delayBeforeRetry = 250, HttpStatusCode statusCode = HttpStatusCode.OK, string httpMethod = "GET", string jsonPayload = "") { if (delayBeforeFirstTry > 0) { await Task.Delay(delayBeforeFirstTry); } HttpResponseMessage response = null; HttpClient client = new HttpClient(new WebRequestHandler { Credentials = credentials, // Disable caching to make sure we always get fresh data from the test site CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore) }); client.Timeout = TimeSpan.FromSeconds(200); client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("Kudu-Test", "1.0")); client.MaxResponseContentBufferSize = 30 * 1024 * 1024; Exception lastException = null; while (true) { try { if (String.Equals(httpMethod, "POST")) { response = await client.PostAsync(siteUrl, new StringContent(jsonPayload, Encoding.UTF8, "application/json")); } else { response = await client.GetAsync(siteUrl); } if (response.StatusCode == statusCode) { return(response); } throw new Exception(string.Format("Mismatch response status {0} != {1}, IsApplicationError: {2}", statusCode, response.StatusCode, IsApplicationError(response))); } catch (Exception ex) { lastException = ex; } retries--; var message = string.Format("Wait for site {0} failed with {1}", siteUrl, lastException.Message); if (retries > 0) { TestTracer.Trace("retries: {0}, {1}", retries, message); await Task.Delay(delayBeforeRetry); } else { throw new Exception(message, lastException); } } }
public static ApplicationManager CreateApplication(string applicationName, string testName = null) { // Default the test name to the app name testName = testName ?? applicationName; TestTracer.Trace("Create application - {0}", applicationName); var pathResolver = new DefaultPathResolver(PathHelper.ServiceSitePath, PathHelper.SitesPath); var settingsResolver = new DefaultSettingsResolver(); var siteManager = GetSiteManager(pathResolver, settingsResolver); Site site; if (KuduUtils.ReuseSameSiteForAllTests) { // In site reuse mode, try to get the existing site, and create it if needed site = siteManager.GetSite(applicationName); if (site == null) { site = siteManager.CreateSite(applicationName); } } else { try { siteManager.DeleteSite(applicationName); } catch (Exception) { } site = siteManager.CreateSite(applicationName); } TestTracer.Trace("Using site - {0}", site.SiteUrl); string gitUrl = null; var repositoryManager = new RemoteRepositoryManager(site.ServiceUrl + "scm"); var repositoryInfo = repositoryManager.GetRepositoryInfo().Result; gitUrl = repositoryInfo.GitUrl.ToString(); var applicationManager = new ApplicationManager(siteManager, site, applicationName, gitUrl, settingsResolver) { SiteUrl = site.SiteUrl, ServiceUrl = site.ServiceUrl, DeploymentManager = new RemoteDeploymentManager(site.ServiceUrl + "deployments"), SettingsManager = new RemoteDeploymentSettingsManager(site.ServiceUrl + "settings"), LogStreamManager = new RemoteLogStreamManager(site.ServiceUrl + "logstream"), SSHKeyManager = new RemoteSSHKeyManager(site.ServiceUrl + "sshkey"), VfsManager = new RemoteVfsManager(site.ServiceUrl + "vfs"), VfsWebRootManager = new RemoteVfsManager(site.ServiceUrl + "vfs/site/wwwroot"), LiveScmVfsManager = new RemoteVfsManager(site.ServiceUrl + "scmvfs"), ZipManager = new RemoteZipManager(site.ServiceUrl + "zip"), CommandExecutor = new RemoteCommandExecutor(site.ServiceUrl + "command"), RepositoryManager = repositoryManager, }; return(applicationManager); }
private static async Task <ApplicationManager> CreateApplicationInternal(int siteIndex) { string applicationName = _sitePrefix + siteIndex; string operationName = "SitePool.CreateApplicationInternal " + applicationName; var context = new KuduTestContext(); var siteManager = GetSiteManager(context); Site site = siteManager.GetSite(applicationName); if (site != null) { TestTracer.Trace("{0} Site already exists at {1}. Reusing site", operationName, site.SiteUrl); TestTracer.Trace("{0} Reset existing site content", operationName); await siteManager.ResetSiteContent(applicationName); RunAgainstCustomKuduUrlIfRequired(site); var appManager = new ApplicationManager(siteManager, site, applicationName) { SitePoolIndex = siteIndex }; // Make sure we start with the correct default file as some tests expect it WriteIndexHtml(appManager); TestTracer.Trace("{0} completed", operationName); return(appManager); } else { TestTracer.Trace("{0} Creating new site", operationName); lock (_createSiteLock) { if (ConfigurationManager.AppSettings["UseNetworkServiceIdentity"] == "true") { var applicationsPath = context.Configuration.ApplicationsPath; if (!Directory.Exists(applicationsPath)) { Directory.CreateDirectory(applicationsPath); var accessRule = new FileSystemAccessRule("NETWORK SERVICE", fileSystemRights: FileSystemRights.Modify | FileSystemRights.Write | FileSystemRights.ReadAndExecute | FileSystemRights.Read | FileSystemRights.ListDirectory, inheritanceFlags: InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, propagationFlags: PropagationFlags.None, type: AccessControlType.Allow); var directoryInfo = new DirectoryInfo(applicationsPath); DirectorySecurity directorySecurity = directoryInfo.GetAccessControl(); directorySecurity.AddAccessRule(accessRule); directoryInfo.SetAccessControl(directorySecurity); } } site = siteManager.CreateSiteAsync(applicationName).Result; RunAgainstCustomKuduUrlIfRequired(site); } TestTracer.Trace("{0} Created new site at {1}", operationName, site.SiteUrl); return(new ApplicationManager(siteManager, site, applicationName) { SitePoolIndex = siteIndex }); } }