Пример #1
0
        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);
            }
        }
Пример #2
0
        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));
            }
        }
Пример #3
0
        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
                });
            }
        }
Пример #4
0
        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);
        }
Пример #5
0
 private static void OnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
 {
     TestTracer.Trace("OnUnobservedTaskException - {0}", e.Exception.GetBaseException());
     e.SetObserved();
 }
Пример #6
0
        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);
                }
            }
        }
Пример #7
0
        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);
        }
Пример #8
0
        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
                });
            }
        }