From f0dea44b4de0bae48a68bb7d963d316f29363d79 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 8 Jul 2020 15:47:26 +1000 Subject: [PATCH] Adds Load Test controller to test data project (instead of just being stored in my personal repo) --- src/Umbraco.TestData/LoadTestController.cs | 371 +++++++++++++++++++ src/Umbraco.TestData/Umbraco.TestData.csproj | 1 + src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 7 +- 3 files changed, 378 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.TestData/LoadTestController.cs diff --git a/src/Umbraco.TestData/LoadTestController.cs b/src/Umbraco.TestData/LoadTestController.cs new file mode 100644 index 0000000000..97665dd084 --- /dev/null +++ b/src/Umbraco.TestData/LoadTestController.cs @@ -0,0 +1,371 @@ +using System; +using System.Threading; +using System.Linq; +using System.Web.Mvc; +using Umbraco.Core.Services; +using Umbraco.Core.Models; +using System.Web; +using System.Web.Hosting; +using System.Web.Routing; +using System.Diagnostics; +using Umbraco.Core.Composing; +using System.Configuration; + +// see https://github.com/Shazwazza/UmbracoScripts/tree/master/src/LoadTesting + +namespace Umbraco.TestData +{ + public class LoadTestController : Controller + { + public LoadTestController(ServiceContext serviceContext) + { + _serviceContext = serviceContext; + } + + private static readonly Random _random = new Random(); + private static readonly object _locko = new object(); + + private static volatile int _containerId = -1; + + private const string _containerAlias = "LoadTestContainer"; + private const string _contentAlias = "LoadTestContent"; + private const int _textboxDefinitionId = -88; + private const int _maxCreate = 1000; + + private static readonly string HeadHtml = @" + + LoadTest + + + +
+

LoadTest

+
" + System.Configuration.ConfigurationManager.AppSettings["umbracoConfigurationStatus"] + @"
+
+"; + + private const string FootHtml = @" +"; + + private static readonly string _containerTemplateText = @" +@inherits Umbraco.Web.Mvc.UmbracoViewPage +@{ + 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 = Request.QueryString[""u""] == ""1""; + var missing = contents.Length > 0 && contents[contents.Length - 1].Id - contents[0].Id >= contents.Length; +} +" + HeadHtml + @" +
+@contents.Length items +
    +@foreach (var group in groups) +{ +
  • @group.Key: @group.Count()
  • +} +
+
+@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 ServiceContext _serviceContext; + + private ActionResult ContentHtml(string s) + { + return Content(HeadHtml + s + FootHtml); + } + + public ActionResult Index() + { + var res = EnsureInitialize(); + if (res != null) return res; + + var html = @"Welcome. You can: + +"; + + return ContentHtml(html); + } + + private ActionResult EnsureInitialize() + { + if (_containerId > 0) return null; + + lock (_locko) + { + if (_containerId > 0) return null; + + var contentTypeService = _serviceContext.ContentTypeService; + 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 contentService = _serviceContext.ContentService; + 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; + } + } + + public ActionResult Install() + { + var dataTypeService = _serviceContext.DataTypeService; + + //var dataType = dataTypeService.GetAll(Constants.DataTypes.DefaultContentListView); + + + //if (!dict.ContainsKey("pageSize")) dict["pageSize"] = new PreValue("10"); + //dict["pageSize"].Value = "200"; + //dataTypeService.SavePreValues(dataType, dict); + + var contentTypeService = _serviceContext.ContentTypeService; + + var contentType = new ContentType(-1) + { + Alias = _contentAlias, + Name = "LoadTest Content", + Description = "Content for LoadTest", + Icon = "icon-document" + }; + var def = _serviceContext.DataTypeService.GetDataType(_textboxDefinitionId); + contentType.AddPropertyType(new PropertyType(def) + { + Name = "Origin", + Alias = "origin", + Description = "The origin of the content.", + }); + contentTypeService.Save(contentType); + + var containerTemplate = ImportTemplate(_serviceContext, + "LoadTestContainer", "LoadTestContainer", _containerTemplateText); + + var containerType = new ContentType(-1) + { + Alias = _containerAlias, + Name = "LoadTest Container", + Description = "Container for LoadTest content", + Icon = "icon-document", + AllowedAsRoot = true, + IsContainer = true + }; + containerType.AllowedContentTypes = containerType.AllowedContentTypes.Union(new[] + { + new ContentTypeSort(new Lazy(() => contentType.Id), 0, contentType.Alias), + }); + containerType.AllowedTemplates = containerType.AllowedTemplates.Union(new[] { containerTemplate }); + containerType.SetDefaultTemplate(containerTemplate); + contentTypeService.Save(containerType); + + var contentService = _serviceContext.ContentService; + var content = contentService.Create("LoadTestContainer", -1, _containerAlias); + contentService.SaveAndPublish(content); + + return ContentHtml("Installed."); + } + + public ActionResult 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); + + var contentService = _serviceContext.ContentService; + + if (n < 1) n = 1; + if (n > _maxCreate) n = _maxCreate; + for (int 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.SaveAndPublish(content); + } + + if (restart) + DoRestart(); + + return ContentHtml("Created " + n + " content" + + (restart ? ", and restarted" : "") + + "."); + } + + private int GetRandom(int minValue, int maxValue) + { + lock (_locko) + { + return _random.Next(minValue, maxValue); + } + } + + public ActionResult Clear() + { + var res = EnsureInitialize(); + if (res != null) return res; + + var contentType = _serviceContext.ContentTypeService.Get(_contentAlias); + _serviceContext.ContentService.DeleteOfType(contentType.Id); + + return ContentHtml("Cleared."); + } + + private void DoRestart() + { + HttpContext.User = null; + System.Web.HttpContext.Current.User = null; + Thread.CurrentPrincipal = null; + HttpRuntime.UnloadAppDomain(); + } + + public ActionResult Restart() + { + DoRestart(); + + return ContentHtml("Restarted."); + } + + public ActionResult Die() + { + var timer = new System.Threading.Timer(_ => + { + throw new Exception("die!"); + }); + timer.Change(100, 0); + + return ContentHtml("Dying."); + } + + public ActionResult Domains() + { + var currentDomain = AppDomain.CurrentDomain; + var currentName = currentDomain.FriendlyName; + var pos = currentName.IndexOf('-'); + if (pos > 0) currentName = currentName.Substring(0, pos); + + var text = new System.Text.StringBuilder(); + text.Append("
Process ID: " + Process.GetCurrentProcess().Id + "
"); + text.Append("
"); + text.Append("
IIS Site: " + HostingEnvironment.ApplicationHost.GetSiteName() + "
"); + text.Append("
App ID: " + currentName + "
"); + //text.Append("
AppPool: " + Zbu.WebManagement.AppPoolHelper.GetCurrentApplicationPoolName() + "
"); + text.Append("
"); + + text.Append("
Domains:
    "); + text.Append("
  • Not implemented.
  • "); + /* + foreach (var domain in Zbu.WebManagement.AppDomainHelper.GetAppDomains().OrderBy(x => x.Id)) + { + var name = domain.FriendlyName; + pos = name.IndexOf('-'); + if (pos > 0) name = name.Substring(0, pos); + text.Append("
  • " + +"[" + domain.Id + "] " + name + + (domain.IsDefaultAppDomain() ? " (default)" : "") + + (domain.Id == currentDomain.Id ? " (current)" : "") + + "
  • "); + } + */ + text.Append("
"); + + return ContentHtml(text.ToString()); + } + + public ActionResult Recycle() + { + return ContentHtml("Not implemented—please use IIS console."); + } + + private static Template ImportTemplate(ServiceContext svces, string name, string alias, string text, ITemplate master = null) + { + var t = new Template(name, alias) { Content = text }; + if (master != null) + t.SetMasterTemplate(master); + svces.FileService.SaveTemplate(t); + return t; + } + } + + public class TestComponent : IComponent + { + public void Initialize() + { + if (ConfigurationManager.AppSettings["Umbraco.TestData.Enabled"] != "true") + return; + + RouteTable.Routes.MapRoute( + name: "LoadTest", + url: "LoadTest/{action}", + defaults: new + { + controller = "LoadTest", + action = "Index" + }, + namespaces: new[] { "Umbraco.TestData" } + ); + } + + public void Terminate() + { + } + } + + public class TestComposer : ComponentComposer, IUserComposer + { + public override void Compose(Composition composition) + { + base.Compose(composition); + + if (ConfigurationManager.AppSettings["Umbraco.TestData.Enabled"] != "true") + return; + + composition.Register(typeof(LoadTestController), Lifetime.Request); + } + } +} diff --git a/src/Umbraco.TestData/Umbraco.TestData.csproj b/src/Umbraco.TestData/Umbraco.TestData.csproj index d61321ebb8..a3753cc17b 100644 --- a/src/Umbraco.TestData/Umbraco.TestData.csproj +++ b/src/Umbraco.TestData/Umbraco.TestData.csproj @@ -41,6 +41,7 @@ + diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 0de757531a..009659c0e2 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -12,7 +12,8 @@ {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} OnBuildSuccess true - 44331 + + enabled disabled false @@ -126,6 +127,10 @@ {52ac0ba8-a60e-4e36-897b-e8b97a54ed1c} Umbraco.ModelsBuilder.Embedded + + {fb5676ed-7a69-492c-b802-e7b24144c0fc} + Umbraco.TestData + {651e1350-91b6-44b7-bd60-7207006d7003} Umbraco.Web