using System; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Threading; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Hosting; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Extensions; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Strings; using IHostingEnvironment = Umbraco.Cms.Core.Hosting.IHostingEnvironment; // see https://github.com/Shazwazza/UmbracoScripts/tree/master/src/LoadTesting namespace Umbraco.TestData; public class LoadTestController : Controller { private const string ContainerAlias = "LoadTestContainer"; private const string ContentAlias = "LoadTestContent"; private const int TextboxDefinitionId = -88; private const int MaxCreate = 1000; private const string FootHtml = @" "; private static readonly Random _random = new(); private static readonly Lock _locko = new(); private static volatile int _containerId = -1; private static readonly string _headHtml = @" LoadTest

LoadTest

@_umbracoVersion.SemanticVersion.ToSemanticStringWithoutBuild()
"; private static readonly string _containerTemplateText = @" @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage @inject Umbraco.Cms.Core.Configuration.IUmbracoVersion _umbracoVersion @{ Layout = null; var container = Umbraco.ContentAtRoot().OfTypes(""" + ContainerAlias + @""").FirstOrDefault(); var contents = container.Children().ToArray(); var groups = contents.GroupBy(x => x.Value(""origin"")); var id = contents.Length > 0 ? contents[0].Id : -1; var wurl = Context.Request.Query[""u""] == ""1""; var missing = contents.Length > 0 && contents[contents.Length - 1].Id - contents[0].Id >= contents.Length; } " + _headHtml + @"
@contents.Length items
@foreach (var content in contents) { while (content.Id > id) {
@id :: MISSING
id++; } if (wurl) {
@content.Id :: @content.Name :: @content.Url()
} else {
@content.Id :: @content.Name
} id++; }
" + FootHtml; private readonly IContentService _contentService; private readonly IContentTypeService _contentTypeService; private readonly IDataTypeService _dataTypeService; private readonly IFileService _fileService; private readonly IHostApplicationLifetime _hostApplicationLifetime; private readonly IHostEnvironment _hostEnvironment; private readonly IShortStringHelper _shortStringHelper; public LoadTestController( IContentTypeService contentTypeService, IContentService contentService, IDataTypeService dataTypeService, IFileService fileService, IShortStringHelper shortStringHelper, IHostEnvironment hostEnvironment, IHostApplicationLifetime hostApplicationLifetime) { _contentTypeService = contentTypeService; _contentService = contentService; _dataTypeService = dataTypeService; _fileService = fileService; _shortStringHelper = shortStringHelper; _hostEnvironment = hostEnvironment; _hostApplicationLifetime = hostApplicationLifetime; } public IActionResult Index() { var res = EnsureInitialize(); if (res != null) { return res; } var html = @"Welcome. You can: "; return ContentHtml(html); } private IActionResult EnsureInitialize() { if (_containerId > 0) { return null; } lock (_locko) { if (_containerId > 0) { return null; } var contentType = _contentTypeService.Get(ContentAlias); if (contentType == null) { return ContentHtml("Not installed, first you must install."); } var containerType = _contentTypeService.Get(ContainerAlias); if (containerType == null) { return ContentHtml("Panic! Container type is missing."); } var container = _contentService.GetPagedOfType(containerType.Id, 0, 100, out _, null).FirstOrDefault(); if (container == null) { return ContentHtml("Panic! Container is missing."); } _containerId = container.Id; return null; } } private IActionResult ContentHtml(string s) => Content(_headHtml + s + FootHtml, "text/html"); public IActionResult Install() { var contentType = new ContentType(_shortStringHelper, -1) { Alias = ContentAlias, Name = "LoadTest Content", Description = "Content for LoadTest", Icon = "icon-document" }; var def = _dataTypeService.GetDataType(TextboxDefinitionId); contentType.AddPropertyType(new PropertyType(_shortStringHelper, def) { Name = "Origin", Alias = "origin", Description = "The origin of the content." }); _contentTypeService.Save(contentType); var containerTemplate = ImportTemplate( "LoadTestContainer", "LoadTestContainer", _containerTemplateText); var containerType = new ContentType(_shortStringHelper, -1) { Alias = ContainerAlias, Name = "LoadTest Container", Description = "Container for LoadTest content", Icon = "icon-document", AllowedAsRoot = true, ListView = Constants.DataTypes.Guids.ListViewContentGuid, }; containerType.AllowedContentTypes = containerType.AllowedContentTypes.Union(new[] { new ContentTypeSort(contentType.Key, 0, contentType.Alias) }); containerType.AllowedTemplates = containerType.AllowedTemplates.Union(new[] { containerTemplate }); containerType.SetDefaultTemplate(containerTemplate); _contentTypeService.Save(containerType); var content = _contentService.Create("LoadTestContainer", -1, ContainerAlias); _contentService.Save(content); _contentService.Publish(content, content.AvailableCultures.ToArray()); return ContentHtml("Installed."); } private Template ImportTemplate(string name, string alias, string text, ITemplate master = null) { var t = new Template(_shortStringHelper, name, alias) { Content = text }; if (master != null) { t.SetMasterTemplate(master); } _fileService.SaveTemplate(t); return t; } public IActionResult Create(int n = 1, int r = 0, string o = null) { var res = EnsureInitialize(); if (res != null) { return res; } if (r < 0) { r = 0; } if (r > 100) { r = 100; } var restart = GetRandom(0, 100) > 100 - r; if (n < 1) { n = 1; } if (n > MaxCreate) { n = MaxCreate; } for (var i = 0; i < n; i++) { var name = Guid.NewGuid().ToString("N").ToUpper() + "-" + (restart ? "R" : "X") + "-" + o; var content = _contentService.Create(name, _containerId, ContentAlias); content.SetValue("origin", o); _contentService.Save(content); _contentService.Publish(content, content.AvailableCultures.ToArray()); } if (restart) { DoRestart(); } return ContentHtml("Created " + n + " content" + (restart ? ", and restarted" : string.Empty) + "."); } private static int GetRandom(int minValue, int maxValue) { lock (_locko) { return _random.Next(minValue, maxValue); } } public IActionResult Clear() { var res = EnsureInitialize(); if (res != null) { return res; } var contentType = _contentTypeService.Get(ContentAlias); _contentService.DeleteOfType(contentType.Id); return ContentHtml("Cleared."); } private void DoRestart() { HttpContext.User = null; Thread.CurrentPrincipal = null; _hostApplicationLifetime.StopApplication(); } public IActionResult ColdBootRestart() { Directory.Delete( _hostEnvironment.MapPathContentRoot(Path.Combine(Constants.SystemDirectories.TempData, "DistCache")), true); DoRestart(); return Content("Cold Boot Restarted."); } public IActionResult Restart() { DoRestart(); return ContentHtml("Restarted."); } public IActionResult Die() { var timer = new Timer(_ => throw new Exception("die!")); _ = timer.Change(100, 0); return ContentHtml("Dying."); } public IActionResult Domains() { var currentDomain = AppDomain.CurrentDomain; var currentName = currentDomain.FriendlyName; var pos = currentName.IndexOf('-'); if (pos > 0) { currentName = currentName[..pos]; } var text = new StringBuilder(); text.Append("
Process ID: " + Process.GetCurrentProcess().Id + "
"); text.Append("
"); // TODO (V9): Commented out as I assume not available? ////text.Append("
IIS Site: " + HostingEnvironment.ApplicationHost.GetSiteName() + "
"); text.Append("
App ID: " + currentName + "
"); //text.Append("
AppPool: " + Zbu.WebManagement.AppPoolHelper.GetCurrentApplicationPoolName() + "
"); text.Append("
"); text.Append("
Domains:
"); return ContentHtml(text.ToString()); } }