diff --git a/src/Umbraco.Compat7/Umbraco.Compat7.csproj b/src/Umbraco.Compat7/Umbraco.Compat7.csproj
index 079cf0fac8..a95a929b34 100644
--- a/src/Umbraco.Compat7/Umbraco.Compat7.csproj
+++ b/src/Umbraco.Compat7/Umbraco.Compat7.csproj
@@ -31,8 +31,6 @@
-
-
diff --git a/src/Umbraco.Core/Events/EventDefinitionBase.cs b/src/Umbraco.Core/Events/EventDefinitionBase.cs
index c0a061f80f..909868ac5b 100644
--- a/src/Umbraco.Core/Events/EventDefinitionBase.cs
+++ b/src/Umbraco.Core/Events/EventDefinitionBase.cs
@@ -7,27 +7,26 @@ namespace Umbraco.Core.Events
{
protected EventDefinitionBase(object sender, object args, string eventName = null)
{
- if (sender == null) throw new ArgumentNullException("sender");
- if (args == null) throw new ArgumentNullException("args");
- Sender = sender;
- Args = args;
+ Sender = sender ?? throw new ArgumentNullException(nameof(sender));
+ Args = args ?? throw new ArgumentNullException(nameof(args));
EventName = eventName;
if (EventName.IsNullOrWhiteSpace())
{
- var findResult = EventNameExtractor.FindEvent(sender, args,
- //don't match "Ing" suffixed names
- exclude:EventNameExtractor.MatchIngNames);
+ // don't match "Ing" suffixed names
+ var findResult = EventNameExtractor.FindEvent(sender, args, exclude:EventNameExtractor.MatchIngNames);
if (findResult.Success == false)
- throw new AmbiguousMatchException("Could not automatically find the event name, the event name will need to be explicitly registered for this event definition. Error: " + findResult.Result.Error);
+ throw new AmbiguousMatchException("Could not automatically find the event name, the event name will need to be explicitly registered for this event definition. "
+ + $"Sender: {sender.GetType()} Args: {args.GetType()}"
+ + " Error: " + findResult.Result.Error);
EventName = findResult.Result.Name;
}
}
- public object Sender { get; private set; }
- public object Args { get; private set; }
- public string EventName { get; private set; }
+ public object Sender { get; }
+ public object Args { get; }
+ public string EventName { get; }
public abstract void RaiseEvent();
diff --git a/src/Umbraco.Core/Events/EventNameExtractor.cs b/src/Umbraco.Core/Events/EventNameExtractor.cs
index 33137770d4..b46948af80 100644
--- a/src/Umbraco.Core/Events/EventNameExtractor.cs
+++ b/src/Umbraco.Core/Events/EventNameExtractor.cs
@@ -40,7 +40,7 @@ namespace Umbraco.Core.Events
{
var events = CandidateEvents.GetOrAdd(senderType, t =>
{
- return t.GetEvents(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
+ return t.GetEvents(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy)
//we can only look for events handlers with generic types because that is the only
// way that we can try to find a matching event based on the arg type passed in
.Where(x => x.EventHandlerType.IsGenericType)
diff --git a/src/Umbraco.Core/IO/FileSystems.cs b/src/Umbraco.Core/IO/FileSystems.cs
index 20a474f71d..adf62397a8 100644
--- a/src/Umbraco.Core/IO/FileSystems.cs
+++ b/src/Umbraco.Core/IO/FileSystems.cs
@@ -343,6 +343,8 @@ namespace Umbraco.Core.IO
internal ICompletable Shadow(Guid id)
{
+ if (Volatile.Read(ref _wkfsInitialized) == false) EnsureWellKnownFileSystems();
+
var typed = _wrappers.ToArray();
var wrappers = new ShadowWrapper[typed.Length + 7];
var i = 0;
diff --git a/src/Umbraco.Core/IO/ShadowFileSystems.cs b/src/Umbraco.Core/IO/ShadowFileSystems.cs
index 1bfa2ebc18..f1ca0bffd9 100644
--- a/src/Umbraco.Core/IO/ShadowFileSystems.cs
+++ b/src/Umbraco.Core/IO/ShadowFileSystems.cs
@@ -13,6 +13,9 @@ namespace Umbraco.Core.IO
// fixme - why are we managing logical call context here? should be bound
// to the current scope, always => REFACTOR! but there should be something in
// place (static?) to ensure we only have one concurrent shadow FS?
+ //
+ // => yes, that's _currentId - need to cleanup this entirely
+ // and, we probably need a way to stop shadowing entirely without cycling the app
private const string ItemKey = "Umbraco.Core.IO.ShadowFileSystems";
diff --git a/src/Umbraco.Core/Models/PublicAccessEntry.cs b/src/Umbraco.Core/Models/PublicAccessEntry.cs
index 5989f885cb..a458ce925a 100644
--- a/src/Umbraco.Core/Models/PublicAccessEntry.cs
+++ b/src/Umbraco.Core/Models/PublicAccessEntry.cs
@@ -27,6 +27,9 @@ namespace Umbraco.Core.Models
_ruleCollection = new ObservableCollection(ruleCollection);
_ruleCollection.CollectionChanged += _ruleCollection_CollectionChanged;
+
+ foreach (var rule in _ruleCollection)
+ rule.AccessEntryId = Key;
}
public PublicAccessEntry(Guid id, int protectedNodeId, int loginNodeId, int noAccessNodeId, IEnumerable ruleCollection)
@@ -40,6 +43,9 @@ namespace Umbraco.Core.Models
_ruleCollection = new ObservableCollection(ruleCollection);
_ruleCollection.CollectionChanged += _ruleCollection_CollectionChanged;
+
+ foreach (var rule in _ruleCollection)
+ rule.AccessEntryId = Key;
}
void _ruleCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
diff --git a/src/Umbraco.Core/Persistence/FaultHandling/RetryDbConnection.cs b/src/Umbraco.Core/Persistence/FaultHandling/RetryDbConnection.cs
index 24e7aeb495..ed438ccbc1 100644
--- a/src/Umbraco.Core/Persistence/FaultHandling/RetryDbConnection.cs
+++ b/src/Umbraco.Core/Persistence/FaultHandling/RetryDbConnection.cs
@@ -142,8 +142,8 @@ namespace Umbraco.Core.Persistence.FaultHandling
protected override void Dispose(bool disposing)
{
- if (disposing && _inner != null)
- _inner.Dispose();
+ if (disposing)
+ _inner?.Dispose();
_inner = null;
base.Dispose(disposing);
}
@@ -153,21 +153,30 @@ namespace Umbraco.Core.Persistence.FaultHandling
_inner.Cancel();
}
- public override string CommandText { get { return _inner.CommandText; } set { _inner.CommandText = value; } }
+ public override string CommandText
+ {
+ get => _inner.CommandText;
+ set => _inner.CommandText = value;
+ }
- public override int CommandTimeout { get { return _inner.CommandTimeout; } set { _inner.CommandTimeout = value; } }
+ public override int CommandTimeout
+ {
+ get => _inner.CommandTimeout;
+ set => _inner.CommandTimeout = value;
+ }
- public override CommandType CommandType { get { return _inner.CommandType; } set { _inner.CommandType = value; } }
+ public override CommandType CommandType
+ {
+ get => _inner.CommandType;
+ set => _inner.CommandType = value;
+ }
protected override DbConnection DbConnection
{
- get
- {
- return _connection;
- }
+ get => _connection;
set
{
- if (value == null) throw new ArgumentNullException("value");
+ if (value == null) throw new ArgumentNullException(nameof(value));
var connection = value as RetryDbConnection;
if (connection == null) throw new ArgumentException("Value is not a FaultHandlingDbConnection instance.");
if (_connection != null && _connection != connection) throw new Exception("Value is another FaultHandlingDbConnection instance.");
@@ -181,12 +190,13 @@ namespace Umbraco.Core.Persistence.FaultHandling
return _inner.CreateParameter();
}
- protected override DbParameterCollection DbParameterCollection
- {
- get { return _inner.Parameters; }
- }
+ protected override DbParameterCollection DbParameterCollection => _inner.Parameters;
- protected override DbTransaction DbTransaction { get { return _inner.Transaction; } set { _inner.Transaction = value; } }
+ protected override DbTransaction DbTransaction
+ {
+ get => _inner.Transaction;
+ set => _inner.Transaction = value;
+ }
public override bool DesignTimeVisible { get; set; }
@@ -219,6 +229,10 @@ namespace Umbraco.Core.Persistence.FaultHandling
_inner.Prepare();
}
- public override UpdateRowSource UpdatedRowSource { get { return _inner.UpdatedRowSource; } set { _inner.UpdatedRowSource = value; } }
+ public override UpdateRowSource UpdatedRowSource
+ {
+ get => _inner.UpdatedRowSource;
+ set => _inner.UpdatedRowSource = value;
+ }
}
}
diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepositoryBase.cs
index 6eb6b74e7c..1e652d829e 100644
--- a/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepositoryBase.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepositoryBase.cs
@@ -1079,51 +1079,30 @@ AND umbracoNode.id <> @id",
// query below is not safe + pointless if array is empty
if (contentTypeIds.Length == 0) return;
- // first part Gets all property groups including property type data even when no property type exists on the group
- // second part Gets all property types including ones that are not on a group
- // therefore the union of the two contains all of the property type and property group information we need
- // NOTE: MySQL requires a SELECT * FROM the inner union in order to be able to sort . lame.
+ var sql = @"SELECT
+ pt.contentTypeId as contentTypeId, pt.uniqueID as ptUniqueID, pt.id as ptId,
+ pt.Alias as ptAlias, pt." + sqlSyntax.GetQuotedColumnName("Description") + @" as ptDesc, pt.mandatory as ptMandatory,
+ pt.Name as ptName, pt.sortOrder as ptSortOrder, pt.validationRegExp as ptRegExp,
- var sqlBuilder = new StringBuilder(@"SELECT PG.contenttypeNodeId as contentTypeId,
- PT.ptUniqueId as ptUniqueID, PT.ptId, PT.ptAlias, PT.ptDesc,PT.ptMandatory,PT.ptName,PT.ptSortOrder,PT.ptRegExp,
- PT.dtId,PT.dtDbType,PT.dtPropEdAlias,
- PG.id as pgId, PG.uniqueID as pgKey, PG.sortorder as pgSortOrder, PG." + sqlSyntax.GetQuotedColumnName("text") + @" as pgText
- FROM cmsPropertyTypeGroup as PG
- LEFT JOIN
- (
- SELECT PT.uniqueID as ptUniqueId, PT.id as ptId, PT.Alias as ptAlias, PT." + sqlSyntax.GetQuotedColumnName("Description") + @" as ptDesc,
- PT.mandatory as ptMandatory, PT.Name as ptName, PT.sortOrder as ptSortOrder, PT.validationRegExp as ptRegExp,
- PT.propertyTypeGroupId as ptGroupId,
- DT.dbType as dtDbType, DT.nodeId as dtId, DT.propertyEditorAlias as dtPropEdAlias
- FROM cmsPropertyType as PT
- INNER JOIN cmsDataType as DT
- ON PT.dataTypeId = DT.nodeId
- ) as PT
- ON PT.ptGroupId = PG.id
- WHERE (PG.contenttypeNodeId in (@contentTypeIds))
+ dt.nodeId as dtId, dt.dbType as dtDbType, dt.propertyEditorAlias as dtPropEdAlias,
- UNION
+ pg.id as pgId, pg.uniqueID as pgKey, pg.sortorder as pgSortOrder, pg." + sqlSyntax.GetQuotedColumnName("text") + @" as pgText
- SELECT PT.contentTypeId as contentTypeId,
- PT.uniqueID as ptUniqueID, PT.id as ptId, PT.Alias as ptAlias, PT." + sqlSyntax.GetQuotedColumnName("Description") + @" as ptDesc,
- PT.mandatory as ptMandatory, PT.Name as ptName, PT.sortOrder as ptSortOrder, PT.validationRegExp as ptRegExp,
- DT.nodeId as dtId, DT.dbType as dtDbType, DT.propertyEditorAlias as dtPropEdAlias,
- PG.id as pgId, PG.uniqueID as pgKey, PG.sortorder as pgSortOrder, PG." + sqlSyntax.GetQuotedColumnName("text") + @" as pgText
- FROM cmsPropertyType as PT
- INNER JOIN cmsDataType as DT
- ON PT.dataTypeId = DT.nodeId
- LEFT JOIN cmsPropertyTypeGroup as PG
- ON PG.id = PT.propertyTypeGroupId
- WHERE (PT.contentTypeId in (@contentTypeIds))");
+FROM cmsPropertyType as pt
+INNER JOIN cmsDataType as dt ON pt.dataTypeId = dt.nodeId
+LEFT JOIN cmsPropertyTypeGroup as pg ON pg.id = pt.propertyTypeGroupId
- sqlBuilder.AppendLine(" ORDER BY (pgId)");
+WHERE pt.contentTypeId IN (@contentTypeIds)
+
+ORDER BY pgId
+";
//NOTE: we are going to assume there's not going to be more than 2100 content type ids since that is the max SQL param count!
// Since there are 2 groups of params, it will be half!
if (((contentTypeIds.Length / 2) - 1) > 2000)
throw new InvalidOperationException("Cannot perform this lookup, too many sql parameters");
- var result = db.Fetch(sqlBuilder.ToString(), new { contentTypeIds = contentTypeIds });
+ var result = db.Fetch(sql, new { contentTypeIds = contentTypeIds });
foreach (var contentTypeId in contentTypeIds)
{
diff --git a/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs b/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs
index b3da57b98b..4a7a5fef7c 100644
--- a/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs
@@ -296,11 +296,6 @@ AND umbracoNode.id <> @id",
return GetCachedPreValueCollection(dataTypeId);
}
- internal static string GetCacheKeyRegex(int preValueId)
- {
- return CacheKeys.DataTypePreValuesCacheKey + @"[-\d]+-([\d]*,)*" + preValueId + @"(?!\d)[,\d$]*";
- }
-
public string GetPreValueAsString(int preValueId)
{
var collections = IsolatedCache.GetCacheItemsByKeySearch(CacheKeys.DataTypePreValuesCacheKey + "_");
diff --git a/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs b/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs
index 687839c943..61c5c74481 100644
--- a/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs
@@ -101,6 +101,10 @@ namespace Umbraco.Core.Persistence.Repositories
Database.Insert(rule);
}
+ //update the id so HasEntity is correct
+ foreach (var rule in entity.Rules)
+ rule.Id = rule.Key.GetHashCode();
+
entity.ResetDirtyProperties();
}
diff --git a/src/Umbraco.Core/Persistence/Repositories/RepositoryBaseOfTIdTEntity.cs b/src/Umbraco.Core/Persistence/Repositories/RepositoryBaseOfTIdTEntity.cs
index 933124e11c..161386b267 100644
--- a/src/Umbraco.Core/Persistence/Repositories/RepositoryBaseOfTIdTEntity.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/RepositoryBaseOfTIdTEntity.cs
@@ -65,6 +65,8 @@ namespace Umbraco.Core.Persistence.Repositories
case RepositoryCacheMode.Scoped:
provider = scope.IsolatedRuntimeCache;
break;
+ case RepositoryCacheMode.None:
+ return new NullCacheProvider(); // fixme cache instance
default:
throw new Exception("oops: cache mode.");
}
@@ -130,17 +132,21 @@ namespace Umbraco.Core.Persistence.Repositories
return _cachePolicy = NoCacheRepositoryCachePolicy.Instance;
// create the cache policy using IsolatedCache which is either global
- // or scoped depending on the repository cache mode for the current scope
- _cachePolicy = CreateCachePolicy(IsolatedCache);
+ // or scoped depending on the repository cache mode for the current scope
var scope = UnitOfWork.Scope;
switch (scope.RepositoryCacheMode)
{
case RepositoryCacheMode.Default:
+ _cachePolicy = CreateCachePolicy(IsolatedCache);
break;
case RepositoryCacheMode.Scoped:
+ _cachePolicy = CreateCachePolicy(IsolatedCache);
var globalIsolatedCache = GetIsolatedCache(GlobalCache.IsolatedRuntimeCache);
_cachePolicy = _cachePolicy.Scoped(globalIsolatedCache, scope);
break;
+ case RepositoryCacheMode.None:
+ _cachePolicy = NoCacheRepositoryCachePolicy.Instance;
+ break;
default:
throw new Exception("oops: cache mode.");
}
diff --git a/src/Umbraco.Core/Persistence/UmbracoDatabase.cs b/src/Umbraco.Core/Persistence/UmbracoDatabase.cs
index 4e7aa45225..a7021bdd57 100644
--- a/src/Umbraco.Core/Persistence/UmbracoDatabase.cs
+++ b/src/Umbraco.Core/Persistence/UmbracoDatabase.cs
@@ -2,6 +2,7 @@ using System;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
+using System.Linq;
using System.Text;
using NPoco;
using StackExchange.Profiling;
@@ -206,7 +207,7 @@ namespace Umbraco.Core.Persistence
_logger.Error("Exception (" + InstanceId + ").", x);
_logger.Debug("At:\r\n" + Environment.StackTrace);
if (EnableSqlTrace == false)
- _logger.Debug("Sql:\r\n" + CommandToString(_cmd));
+ _logger.Debug("Sql:\r\n" + CommandToString(LastSQL, LastArgs));
base.OnException(x);
}
@@ -232,23 +233,28 @@ namespace Umbraco.Core.Persistence
base.OnExecutingCommand(cmd);
}
- private static string CommandToString(DbCommand cmd)
+ private string CommandToString(DbCommand cmd)
+ {
+ return CommandToString(cmd.CommandText, cmd.Parameters.Cast().Select(x => x.Value).ToArray());
+ }
+
+ private string CommandToString(string sql, object[] args)
{
var sb = new StringBuilder();
#if DEBUG_DATABASES
sb.Append(InstanceId);
sb.Append(": ");
#endif
- sb.Append(cmd.CommandText);
- if (cmd.Parameters.Count > 0)
+ sb.Append(sql);
+ if (args.Length > 0)
sb.Append(" --");
var i = 0;
- foreach (DbParameter p in cmd.Parameters)
+ foreach (var arg in args)
{
sb.Append(" @");
sb.Append(i++);
sb.Append(":");
- sb.Append(p.Value);
+ sb.Append(arg);
}
return sb.ToString();
diff --git a/src/Umbraco.Core/Persistence/UnitOfWork/ScopeUnitOfWork.cs b/src/Umbraco.Core/Persistence/UnitOfWork/ScopeUnitOfWork.cs
index 5c268175a2..5a201a7dcc 100644
--- a/src/Umbraco.Core/Persistence/UnitOfWork/ScopeUnitOfWork.cs
+++ b/src/Umbraco.Core/Persistence/UnitOfWork/ScopeUnitOfWork.cs
@@ -52,6 +52,9 @@ namespace Umbraco.Core.Persistence.UnitOfWork
#region IDatabaseContext
+ // fixme - stop using the actual Database here - it forces the creation of the DB
+ // should have a reference to a IDatabaseContext to use instead!
+
///
public ISqlSyntaxProvider SqlSyntax => Database.SqlSyntax;
diff --git a/src/Umbraco.Core/Scoping/RepositoryCacheMode.cs b/src/Umbraco.Core/Scoping/RepositoryCacheMode.cs
index 23cf94d327..8b8fc0cf35 100644
--- a/src/Umbraco.Core/Scoping/RepositoryCacheMode.cs
+++ b/src/Umbraco.Core/Scoping/RepositoryCacheMode.cs
@@ -22,6 +22,16 @@
/// Reads from, and writes to, a scope-local cache.
/// Upon scope completion, clears the global L2 cache.
///
- Scoped = 2
+ Scoped = 2,
+
+ ///
+ /// No cache.
+ ///
+ ///
+ /// Bypasses caches entirely.
+ /// Upon scope completion, clears the global L2 cache.
+ /// fixme - what about a L1 cache?
+ ///
+ None = 3
}
}
diff --git a/src/Umbraco.Core/Scoping/Scope.cs b/src/Umbraco.Core/Scoping/Scope.cs
index dbeb5f1d0d..0074af6ac7 100644
--- a/src/Umbraco.Core/Scoping/Scope.cs
+++ b/src/Umbraco.Core/Scoping/Scope.cs
@@ -65,7 +65,7 @@ namespace Umbraco.Core.Scoping
#if DEBUG_SCOPES
_scopeProvider.RegisterScope(this);
- Console.WriteLine("create " + _instanceId.ToString("N").Substring(0, 8));
+ Console.WriteLine("create " + InstanceId.ToString("N").Substring(0, 8));
#endif
if (detachable)
@@ -88,16 +88,19 @@ namespace Umbraco.Core.Scoping
ParentScope = parent;
// cannot specify a different mode!
- if (repositoryCacheMode != RepositoryCacheMode.Unspecified && parent.RepositoryCacheMode != repositoryCacheMode)
- throw new ArgumentException("Cannot be different from parent.", nameof(repositoryCacheMode));
+ // fixme - means that it's OK to go from L2 to None for reading purposes, but writing would be BAD!
+ // this is for XmlStore that wants to bypass caches when rebuilding XML (same for NuCache)
+ if (repositoryCacheMode != RepositoryCacheMode.Unspecified && parent.RepositoryCacheMode > repositoryCacheMode)
+ throw new ArgumentException($"Value '{repositoryCacheMode}' cannot be lower than parent value '{parent.RepositoryCacheMode}'.", nameof(repositoryCacheMode));
// cannot specify a dispatcher!
if (_eventDispatcher != null)
- throw new ArgumentException("Cannot be specified on nested scope.", nameof(eventDispatcher));
+ throw new ArgumentException("Value cannot be specified on nested scope.", nameof(eventDispatcher));
// cannot specify a different fs scope!
+ // fixme - in fact, can be 'true' only on outer scope, and false does not make much sense
if (scopeFileSystems != null && parent._scopeFileSystem != scopeFileSystems)
- throw new ArgumentException("Cannot be different from parent.", nameof(scopeFileSystems));
+ throw new ArgumentException($"Value '{scopeFileSystems.Value}' be different from parent value '{parent._scopeFileSystem}'.", nameof(scopeFileSystems));
}
else
{
@@ -334,8 +337,11 @@ namespace Umbraco.Core.Scoping
_logger.Debug("Dispose error (" + (ambient == null ? "no" : "other") + " ambient)");
if (ambient == null)
throw new InvalidOperationException("Not the ambient scope (no ambient scope).");
- var infos = _scopeProvider.GetScopeInfo(ambient);
- throw new InvalidOperationException("Not the ambient scope (see current ambient ctor stack trace).\r\n" + infos.CtorStack);
+ var ambientInfos = _scopeProvider.GetScopeInfo(ambient);
+ var disposeInfos = _scopeProvider.GetScopeInfo(this);
+ throw new InvalidOperationException("Not the ambient scope (see ctor stack traces).\r\n"
+ + "- ambient ctor ->\r\n" + ambientInfos.CtorStack + "\r\n"
+ + "- dispose ctor ->\r\n" + disposeInfos.CtorStack + "\r\n");
#else
throw new InvalidOperationException("Not the ambient scope.");
#endif
diff --git a/src/Umbraco.Core/Scoping/ScopeProvider.cs b/src/Umbraco.Core/Scoping/ScopeProvider.cs
index 3318cf81e7..97e5ea5cc3 100644
--- a/src/Umbraco.Core/Scoping/ScopeProvider.cs
+++ b/src/Umbraco.Core/Scoping/ScopeProvider.cs
@@ -3,6 +3,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Runtime.Remoting.Messaging;
+using System.Text;
using System.Web;
using Umbraco.Core.Composing;
using Umbraco.Core.Events;
@@ -110,8 +111,8 @@ namespace Umbraco.Core.Scoping
if (StaticCallContextObjects.TryGetValue(objectKey, out object callContextObject))
{
#if DEBUG_SCOPES
- Logging.LogHelper.Debug("Got " + typeof(T).Name + " Object " + objectKey.ToString("N").Substring(0, 8));
- //Logging.LogHelper.Debug("At:\r\n" + Head(Environment.StackTrace, 24));
+ Current.Logger.Debug("Got " + typeof(T).Name + " Object " + objectKey.ToString("N").Substring(0, 8));
+ //_logger.Debug("At:\r\n" + Head(Environment.StackTrace, 24));
#endif
return (T)callContextObject;
}
@@ -119,7 +120,7 @@ namespace Umbraco.Core.Scoping
// hard to inject into a static method :(
Current.Logger.Warn("Missed " + typeof(T).Name + " Object " + objectKey.ToString("N").Substring(0, 8));
#if DEBUG_SCOPES
- //Logging.LogHelper.Debug("At:\r\n" + Head(Environment.StackTrace, 24));
+ //Current.Logger.Debug("At:\r\n" + Head(Environment.StackTrace, 24));
#endif
return null;
}
@@ -155,8 +156,8 @@ namespace Umbraco.Core.Scoping
lock (StaticCallContextObjectsLock)
{
#if DEBUG_SCOPES
- Logging.LogHelper.Debug("Remove Object " + objectKey.ToString("N").Substring(0, 8));
- //Logging.LogHelper.Debug("At:\r\n" + Head(Environment.StackTrace, 24));
+ Current.Logger.Debug("Remove Object " + objectKey.ToString("N").Substring(0, 8));
+ //Current.Logger.Debug("At:\r\n" + Head(Environment.StackTrace, 24));
#endif
StaticCallContextObjects.Remove(objectKey);
}
@@ -170,8 +171,8 @@ namespace Umbraco.Core.Scoping
lock (StaticCallContextObjectsLock)
{
#if DEBUG_SCOPES
- Logging.LogHelper.Debug("AddObject " + objectKey.ToString("N").Substring(0, 8));
- //Logging.LogHelper.Debug("At:\r\n" + Head(Environment.StackTrace, 24));
+ Current.Logger.Debug("AddObject " + objectKey.ToString("N").Substring(0, 8));
+ //Current.Logger.Debug("At:\r\n" + Head(Environment.StackTrace, 24));
#endif
StaticCallContextObjects.Add(objectKey, value);
}
@@ -466,7 +467,7 @@ namespace Umbraco.Core.Scoping
lock (StaticScopeInfosLock)
{
if (StaticScopeInfos.ContainsKey(scope)) throw new Exception("oops: already registered.");
- Logging.LogHelper.Debug("Register " + scope.InstanceId.ToString("N").Substring(0, 8));
+ _logger.Debug("Register " + scope.InstanceId.ToString("N").Substring(0, 8));
StaticScopeInfos[scope] = new ScopeInfo(scope, Environment.StackTrace);
}
}
@@ -490,12 +491,12 @@ namespace Umbraco.Core.Scoping
{
if (sb.Length > 0) sb.Append(" < ");
sb.Append(s.InstanceId.ToString("N").Substring(0, 8));
- var ss = s as IScopeInternal;
- s = ss == null ? null : ss.ParentScope;
+ var ss = s as Scope;
+ s = ss?.ParentScope;
}
- Logging.LogHelper.Debug("Register " + (context ?? "null") + " context " + sb);
+ Current.Logger.Debug("Register " + (context ?? "null") + " context " + sb);
if (context == null) info.NullStack = Environment.StackTrace;
- //Logging.LogHelper.Debug("At:\r\n" + Head(Environment.StackTrace, 16));
+ //Current.Logger.Debug("At:\r\n" + Head(Environment.StackTrace, 16));
info.Context = context;
}
}
@@ -522,7 +523,7 @@ namespace Umbraco.Core.Scoping
// enable this by default
//Console.WriteLine("unregister " + scope.InstanceId.ToString("N").Substring(0, 8));
StaticScopeInfos.Remove(scope);
- Logging.LogHelper.Debug("Remove " + scope.InstanceId.ToString("N").Substring(0, 8));
+ _logger.Debug("Remove " + scope.InstanceId.ToString("N").Substring(0, 8));
// instead, enable this to keep *all* scopes
// beware, there can be a lot of scopes!
@@ -544,16 +545,16 @@ namespace Umbraco.Core.Scoping
CtorStack = ctorStack;
}
- public IScope Scope { get; private set; } // the scope itself
+ public IScope Scope { get; } // the scope itself
// the scope's parent identifier
- public Guid Parent { get { return (Scope is NoScope || ((Scope) Scope).ParentScope == null) ? Guid.Empty : ((Scope) Scope).ParentScope.InstanceId; } }
+ public Guid Parent => ((Scope) Scope).ParentScope == null ? Guid.Empty : ((Scope) Scope).ParentScope.InstanceId;
- public DateTime Created { get; private set; } // the date time the scope was created
+ public DateTime Created { get; } // the date time the scope was created
public bool Disposed { get; set; } // whether the scope has been disposed already
public string Context { get; set; } // the current 'context' that contains the scope (null, "http" or "lcc")
- public string CtorStack { get; private set; } // the stacktrace of the scope ctor
+ public string CtorStack { get; } // the stacktrace of the scope ctor
public string DisposedStack { get; set; } // the stacktrace when disposed
public string NullStack { get; set; } // the stacktrace when the 'context' that contains the scope went null
}
diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs
index b85f82ee24..7267d1d420 100644
--- a/src/Umbraco.Core/Services/ContentService.cs
+++ b/src/Umbraco.Core/Services/ContentService.cs
@@ -164,7 +164,11 @@ namespace Umbraco.Core.Services
throw new ArgumentException("No content with that id.", nameof(parentId));
var content = new Content(name, parentId, contentType);
- CreateContent(null, content, parent, userId, false);
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ CreateContent(uow, content, parent, userId, false);
+ uow.Complete();
+ }
return content;
}
@@ -189,7 +193,11 @@ namespace Umbraco.Core.Services
throw new ArgumentException("No content type with that alias.", nameof(contentTypeAlias));
var content = new Content(name, -1, contentType);
- CreateContent(null, content, null, userId, false);
+ using (var uow = UowProvider.CreateUnitOfWork())
+ {
+ CreateContent(uow, content, null, userId, false);
+ uow.Complete();
+ }
return content;
}
@@ -940,6 +948,11 @@ namespace Umbraco.Core.Services
return OperationStatus.Attempt.Cancel(evtMsgs);
}
+ if (string.IsNullOrWhiteSpace(content.Name))
+ {
+ throw new ArgumentException("Cannot save content with empty name.");
+ }
+
var isNew = content.IsNewEntity();
uow.WriteLock(Constants.Locks.ContentTree);
@@ -1533,6 +1546,7 @@ namespace Umbraco.Core.Services
// because we want it now, we have to calculate it by ourselves
//paths[content.Id] = content.Path;
paths[content.Id] = (parent == null ? (parentId == Constants.System.RecycleBinContent ? "-1,-20" : "-1") : parent.Path) + "," + content.Id;
+ Console.WriteLine("path " + content.Id + " = " + paths[content.Id]);
var descendants = GetDescendants(content);
foreach (var descendant in descendants)
@@ -1540,14 +1554,16 @@ namespace Umbraco.Core.Services
moves.Add(Tuple.Create(descendant, descendant.Path)); // capture original path
// update path and level since we do not update parentId
+ if (paths.ContainsKey(descendant.ParentId) == false)
+ Console.WriteLine("oops on " + descendant.ParentId + " for " + content.Path + " " + parent?.Path);
descendant.Path = paths[descendant.Id] = paths[descendant.ParentId] + "," + descendant.Id;
+ Console.WriteLine("path " + descendant.Id + " = " + paths[descendant.Id]);
descendant.Level += levelDelta;
PerformMoveContentLocked(repository, descendant, userId, trash);
}
}
- private static void PerformMoveContentLocked(IContentRepository repository, IContent content, int userId,
- bool? trash)
+ private static void PerformMoveContentLocked(IContentRepository repository, IContent content, int userId, bool? trash)
{
if (trash.HasValue) ((ContentBase) content).Trashed = trash.Value;
content.WriterId = userId;
@@ -1868,7 +1884,7 @@ namespace Umbraco.Core.Services
{
uow.ReadLock(Constants.Locks.ContentTree);
var repository = uow.CreateRepository();
- return GetPublishedDescendantsLocked(repository, content);
+ return GetPublishedDescendantsLocked(repository, content).ToArray(); // ToArray important in uow!
}
}
@@ -2067,7 +2083,7 @@ namespace Umbraco.Core.Services
{
if (HasChildren(content.Id))
{
- var descendants = GetPublishedDescendants(content).ToArray();
+ var descendants = GetPublishedDescendantsLocked(repository, content).ToArray();
uow.Events.Dispatch(Published, this, new PublishEventArgs(descendants, false, false), "Published");
}
changeType = TreeChangeTypes.RefreshBranch; // whole branch
diff --git a/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTItemTService.cs b/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTItemTService.cs
index 73a58b1671..7ecc0e361f 100644
--- a/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTItemTService.cs
+++ b/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTItemTService.cs
@@ -39,11 +39,12 @@ namespace Umbraco.Core.Services
protected void OnChanged(IScopeUnitOfWork uow, ContentTypeChange.EventArgs args)
{
- uow.Events.Dispatch(Changed, This, args);
+ uow.Events.Dispatch(Changed, This, args, "Changed");
}
protected void OnUowRefreshedEntity(ContentTypeChange.EventArgs args)
{
+ // that one is always immediate (not dispatched, transactional)
UowRefreshedEntity.RaiseEvent(args, This);
}
diff --git a/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs b/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs
index 0873670f87..88b4e5e2eb 100644
--- a/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs
+++ b/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs
@@ -391,6 +391,9 @@ namespace Umbraco.Core.Services
return;
}
+ if (string.IsNullOrWhiteSpace(item.Name))
+ throw new ArgumentException("Cannot save item with empty name.");
+
var repo = uow.CreateRepository();
uow.WriteLock(WriteLockIds);
@@ -780,7 +783,7 @@ namespace Umbraco.Core.Services
var evtMsgs = EventMessagesFactory.Get();
var containerObjectType = ContainerObjectType;
- if (container.ContainedObjectType != containerObjectType)
+ if (container.ContainerObjectType != containerObjectType)
{
var ex = new InvalidOperationException("Not a container of the proper type.");
return OperationStatus.Attempt.Fail(evtMsgs, ex);
diff --git a/src/Umbraco.Core/Services/MacroService.cs b/src/Umbraco.Core/Services/MacroService.cs
index 27b4a91df5..96249512b3 100644
--- a/src/Umbraco.Core/Services/MacroService.cs
+++ b/src/Umbraco.Core/Services/MacroService.cs
@@ -132,6 +132,11 @@ namespace Umbraco.Core.Services
return;
}
+ if (string.IsNullOrWhiteSpace(macro.Name))
+ {
+ throw new ArgumentException("Cannot save macro with empty name.");
+ }
+
var repository = uow.CreateRepository();
repository.AddOrUpdate(macro);
diff --git a/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj b/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj
index 4866c7da05..acb2af404f 100644
--- a/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj
+++ b/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj
@@ -156,7 +156,6 @@
-
@@ -176,10 +175,6 @@
-
-
-
-
diff --git a/src/Umbraco.Tests/Cache/CacheRefresherComponentTests.cs b/src/Umbraco.Tests/Cache/CacheRefresherComponentTests.cs
index 66ec612b16..ece846e0e4 100644
--- a/src/Umbraco.Tests/Cache/CacheRefresherComponentTests.cs
+++ b/src/Umbraco.Tests/Cache/CacheRefresherComponentTests.cs
@@ -2,23 +2,31 @@
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
+using Umbraco.Core.Composing;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
using Umbraco.Tests.TestHelpers;
+using Umbraco.Tests.Testing;
using Umbraco.Web.Cache;
namespace Umbraco.Tests.Cache
{
[TestFixture]
- public class CacheRefresherEventHandlerTests
+ [UmbracoTest(WithApplication = true)]
+ public class CacheRefresherEventHandlerTests : UmbracoTestBase
{
[Test]
public void Can_Find_All_Event_Handlers()
{
- var testObjects = new TestObjects(null);
- var serviceContext = testObjects.GetServiceContextMock();
+ // fixme - cannot work with mocks
+ // because the events are defined on actual static classes, not on the interfaces, so name matching fails
+ // we should really refactor events entirely - in the meantime, let it be an UmbracoTestBase ;(
+ //var testObjects = new TestObjects(null);
+ //var serviceContext = testObjects.GetServiceContextMock();
+ var serviceContext = Current.Services;
+
var definitions = new IEventDefinition[]
{
//I would test these but they are legacy events and we don't need them for deploy, when we migrate to new/better events we can wire up the check
@@ -58,8 +66,8 @@ namespace Umbraco.Tests.Cache
new EventDefinition>(null, serviceContext.ContentTypeService, new SaveEventArgs(Enumerable.Empty())),
new EventDefinition>(null, serviceContext.ContentTypeService, new DeleteEventArgs(Enumerable.Empty())),
- new EventDefinition>(null, serviceContext.ContentTypeService, new SaveEventArgs(Enumerable.Empty())),
- new EventDefinition>(null, serviceContext.ContentTypeService, new DeleteEventArgs(Enumerable.Empty())),
+ new EventDefinition>(null, serviceContext.MediaTypeService, new SaveEventArgs(Enumerable.Empty())),
+ new EventDefinition>(null, serviceContext.MediaTypeService, new DeleteEventArgs(Enumerable.Empty())),
new EventDefinition>(null, serviceContext.MemberTypeService, new SaveEventArgs(Enumerable.Empty())),
new EventDefinition>(null, serviceContext.MemberTypeService, new DeleteEventArgs(Enumerable.Empty())),
@@ -100,11 +108,17 @@ namespace Umbraco.Tests.Cache
new EventDefinition>(null, serviceContext.RelationService, new DeleteEventArgs(Enumerable.Empty())),
};
+ var ok = true;
foreach (var definition in definitions)
{
var found = CacheRefresherComponent.FindHandler(definition);
- Assert.IsNotNull(found, "Couldn't find method for " + definition.EventName + " on " + definition.Sender.GetType());
+ if (found == null)
+ {
+ Console.WriteLine("Couldn't find method for " + definition.EventName + " on " + definition.Sender.GetType());
+ ok = false;
+ }
}
+ Assert.IsTrue(ok, "see log for details");
}
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Tests/Components/ComponentTests.cs b/src/Umbraco.Tests/Components/ComponentTests.cs
index 581e15cfdc..928a1354fc 100644
--- a/src/Umbraco.Tests/Components/ComponentTests.cs
+++ b/src/Umbraco.Tests/Components/ComponentTests.cs
@@ -6,9 +6,11 @@ using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Components;
+using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Mappers;
+using Umbraco.Core.Scoping;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.Stubs;
@@ -28,11 +30,14 @@ namespace Umbraco.Tests.Components
var logger = Mock.Of();
var s = testObjects.GetDefaultSqlSyntaxProviders(logger);
var f = new UmbracoDatabaseFactory(s, logger, new MapperCollection(Enumerable.Empty()));
+ var fs = new FileSystems(logger);
+ var p = new ScopeProvider(f, fs, logger);
var mock = new Mock();
- mock.Setup(x => x.GetInstance()).Returns(logger);
- mock.Setup(x => x.GetInstance()).Returns(new ProfilingLogger(Mock.Of(), Mock.Of()));
- mock.Setup(x => x.GetInstance()).Returns(f);
+ mock.Setup(x => x.GetInstance(typeof (ILogger))).Returns(logger);
+ mock.Setup(x => x.GetInstance(typeof (ProfilingLogger))).Returns(new ProfilingLogger(Mock.Of(), Mock.Of()));
+ mock.Setup(x => x.GetInstance(typeof (IUmbracoDatabaseFactory))).Returns(f);
+ mock.Setup(x => x.GetInstance(typeof (IScopeProvider))).Returns(p);
setup?.Invoke(mock);
return mock.Object;
}
diff --git a/src/Umbraco.Tests/CoreThings/UdiTests.cs b/src/Umbraco.Tests/CoreThings/UdiTests.cs
index 411803bdd1..debb7faaf9 100644
--- a/src/Umbraco.Tests/CoreThings/UdiTests.cs
+++ b/src/Umbraco.Tests/CoreThings/UdiTests.cs
@@ -1,8 +1,13 @@
using System;
using System.Linq;
+using LightInject;
+using Moq;
using Newtonsoft.Json;
using NUnit.Framework;
using Umbraco.Core;
+using Umbraco.Core.Cache;
+using Umbraco.Core.Composing;
+using Umbraco.Core.Logging;
using Umbraco.Core.Serialization;
namespace Umbraco.Tests.CoreThings
@@ -10,6 +15,21 @@ namespace Umbraco.Tests.CoreThings
[TestFixture]
public class UdiTests
{
+ [SetUp]
+ public void SetUp()
+ {
+ // fixme - bad in a unit test - but Udi has a static ctor that wants it?!
+ var container = new Mock();
+ container.Setup(x => x.GetInstance(typeof (TypeLoader))).Returns(new TypeLoader(new NullCacheProvider(), new ProfilingLogger(Mock.Of(), Mock.Of())));
+ Current.Container = container.Object;
+ }
+
+ [TearDown]
+ public void TearDown()
+ {
+ Current.Reset();
+ }
+
[Test]
public void StringEntityCtorTest()
{
diff --git a/src/Umbraco.Tests/Dependencies/NuGet.cs b/src/Umbraco.Tests/Dependencies/NuGet.cs
index 9a07b488ef..7841210105 100644
--- a/src/Umbraco.Tests/Dependencies/NuGet.cs
+++ b/src/Umbraco.Tests/Dependencies/NuGet.cs
@@ -74,7 +74,7 @@ namespace Umbraco.Tests.Dependencies
// guarantees that all packages have one version, solutionwide, so it's okay to take First() here
if (dependencyMinimumVersion != matchingPackages.First().PackageVersion)
{
- Debug.WriteLine("NuSpec dependency '{0}' with minimum version {1} in doesn't match with version {2} in the solution",
+ Debug.WriteLine("NuSpec dependency '{0}' with minimum version {1} doesn't match with version {2} in the solution",
dependency.Id, dependencyMinimumVersion, matchingPackages.First().PackageVersion);
failTest = true;
}
diff --git a/src/Umbraco.Tests/Issues/U9560.cs b/src/Umbraco.Tests/Issues/U9560.cs
index 0b8bbfe4d5..86c7218876 100644
--- a/src/Umbraco.Tests/Issues/U9560.cs
+++ b/src/Umbraco.Tests/Issues/U9560.cs
@@ -4,11 +4,13 @@ using Umbraco.Core.Models;
using Umbraco.Core.Persistence;
using Umbraco.Tests.Testing;
using LightInject;
+using Umbraco.Tests.TestHelpers;
namespace Umbraco.Tests.Issues
{
- [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)]
- public class U9560 : UmbracoTestBase
+ [TestFixture]
+ [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, WithApplication = true)]
+ public class U9560 : TestWithDatabaseBase
{
[Test]
public void Test()
diff --git a/src/Umbraco.Tests/Membership/MembershipProviderBaseTests.cs b/src/Umbraco.Tests/Membership/MembershipProviderBaseTests.cs
index c786a61996..429737c508 100644
--- a/src/Umbraco.Tests/Membership/MembershipProviderBaseTests.cs
+++ b/src/Umbraco.Tests/Membership/MembershipProviderBaseTests.cs
@@ -8,16 +8,34 @@ using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Web.Security;
+using LightInject;
using Moq;
using NUnit.Framework;
+using Umbraco.Core;
+using Umbraco.Core.Composing;
using Umbraco.Core.Security;
+using Umbraco.Core.Services;
namespace Umbraco.Tests.Membership
{
[TestFixture]
public class MembershipProviderBaseTests
{
-
+ [SetUp]
+ public void SetUp()
+ {
+ Current.Container = new ServiceContainer();
+
+ var mRuntimeState = new Mock();
+ mRuntimeState.Setup(x => x.Level).Returns(() => RuntimeLevel.Run);
+ Current.Container.RegisterSingleton(f => mRuntimeState.Object);
+ }
+
+ [TearDown]
+ public void TearDown()
+ {
+ Current.Reset();
+ }
[Test]
public void Change_Password_Without_AllowManuallyChangingPassword_And_No_Pass_Validation()
@@ -125,7 +143,12 @@ namespace Umbraco.Tests.Membership
Assert.Throws(() => provider.GetPassword("test", "test"));
}
+ // fixme
+ // in v7 this test relies on ApplicationContext.Current being null, which makes little
+ // sense, not going to port the weird code in MembershipProviderBase.ResetPassword, so
+ // what shall we do?
[Test]
+ [Ignore("makes no sense?")]
public void ResetPassword_Without_EnablePasswordReset()
{
var providerMock = new Mock() { CallBase = true };
diff --git a/src/Umbraco.Tests/Persistence/LocksTests.cs b/src/Umbraco.Tests/Persistence/LocksTests.cs
index f58552ad10..e80325b9c2 100644
--- a/src/Umbraco.Tests/Persistence/LocksTests.cs
+++ b/src/Umbraco.Tests/Persistence/LocksTests.cs
@@ -69,7 +69,7 @@ namespace Umbraco.Tests.Persistence
lock (locker)
{
acquired++;
- if (acquired == 5) m2.Set();
+ if (acquired == threadCount) m2.Set();
}
m1.Wait();
lock (locker)
@@ -99,7 +99,7 @@ namespace Umbraco.Tests.Persistence
foreach (var thread in threads) thread.Join();
- Assert.AreEqual(5, maxAcquired);
+ Assert.AreEqual(threadCount, maxAcquired);
Assert.AreEqual(0, acquired);
for (var i = 0; i < threadCount; i++)
@@ -115,8 +115,8 @@ namespace Umbraco.Tests.Persistence
var locker = new object();
var acquired = 0;
var entered = 0;
- var ms = new AutoResetEvent[5];
- for (var i = 0; i < 5; i++) ms[i] = new AutoResetEvent(false);
+ var ms = new AutoResetEvent[threadCount];
+ for (var i = 0; i < threadCount; i++) ms[i] = new AutoResetEvent(false);
var m1 = new ManualResetEventSlim(false);
for (var i = 0; i < threadCount; i++)
@@ -131,7 +131,7 @@ namespace Umbraco.Tests.Persistence
lock (locker)
{
entered++;
- if (entered == 5) m1.Set();
+ if (entered == threadCount) m1.Set();
}
ms[ic].WaitOne();
scope.Database.AcquireLockNodeWriteLock(Constants.Locks.Servers);
@@ -164,11 +164,11 @@ namespace Umbraco.Tests.Persistence
// all threads have entered
ms[0].Set(); // let 0 go
Thread.Sleep(100);
- for (var i = 1; i < 5; i++) ms[i].Set(); // let others go
+ for (var i = 1; i < threadCount; i++) ms[i].Set(); // let others go
Thread.Sleep(500);
// only 1 thread has locked
Assert.AreEqual(1, acquired);
- for (var i = 0; i < 5; i++) ms[i].Set(); // let all go
+ for (var i = 0; i < threadCount; i++) ms[i].Set(); // let all go
foreach (var thread in threads) thread.Join();
diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs
index b1261bd21e..918213f25c 100644
--- a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs
+++ b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs
@@ -85,21 +85,23 @@ namespace Umbraco.Tests.Persistence.Repositories
contentTypeRepository.AddOrUpdate(hasPropertiesContentType);
repository.AddOrUpdate(content1);
unitOfWork.Flush();
- versions.Add(content1.Version);
+ versions.Add(content1.Version); // the first version
//publish version
- content1.ChangePublishedState(PublishedState.Published);
+ content1.ChangePublishedState(PublishedState.Publishing);
repository.AddOrUpdate(content1);
unitOfWork.Flush();
- versions.Add(content1.Version);
+ versions.Add(content1.Version); // the first version got published, same id
//change something and make a pending version
content1.Name = "new name";
+ if (content1.Published)
+ content1.ChangePublishedState(PublishedState.Saving);
repository.AddOrUpdate(content1);
unitOfWork.Flush();
- versions.Add(content1.Version);
+ versions.Add(content1.Version); // the second version
- Assert.AreEqual(3, versions.Distinct().Count());
+ Assert.AreEqual(2, versions.Distinct().Count());
var content = repository.GetByQuery(unitOfWork.Query().Where(c => c.Id == content1.Id)).ToArray()[0];
Assert.AreEqual(versions[2], content.Version);
diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs
index 778ae12687..ae00e5dbe5 100644
--- a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs
+++ b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs
@@ -8,13 +8,9 @@ using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
-using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Rdbms;
-using Umbraco.Core.Persistence;
-using Umbraco.Core.Persistence.Querying;
-using Umbraco.Core.Persistence.Mappers;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Tests.TestHelpers;
@@ -761,6 +757,9 @@ namespace Umbraco.Tests.Persistence.Repositories
var repository = CreateRepository(unitOfWork);
var contentType = repository.Get(NodeDto.NodeIdSeed + 1);
+ Assert.That(contentType.PropertyGroups.Count, Is.EqualTo(2));
+ Assert.That(contentType.PropertyTypes.Count(), Is.EqualTo(4));
+
// Act
var urlAlias = new PropertyType("test", DataTypeDatabaseType.Nvarchar, "urlAlias")
{
@@ -772,13 +771,17 @@ namespace Umbraco.Tests.Persistence.Repositories
};
var addedPropertyType = contentType.AddPropertyType(urlAlias);
+
+ Assert.That(contentType.PropertyGroups.Count, Is.EqualTo(2));
+ Assert.That(contentType.PropertyTypes.Count(), Is.EqualTo(5));
+
repository.AddOrUpdate(contentType);
unitOfWork.Flush();
// Assert
var updated = repository.Get(NodeDto.NodeIdSeed + 1);
Assert.That(addedPropertyType, Is.True);
- Assert.That(updated.PropertyGroups.Count(), Is.EqualTo(2));
+ Assert.That(updated.PropertyGroups.Count, Is.EqualTo(2));
Assert.That(updated.PropertyTypes.Count(), Is.EqualTo(5));
Assert.That(updated.PropertyTypes.Any(x => x.Alias == "urlAlias"), Is.True);
Assert.That(updated.PropertyTypes.First(x => x.Alias == "urlAlias").PropertyGroupId, Is.Null);
diff --git a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs
index 0f07ff3c57..1811b9e3b2 100644
--- a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs
+++ b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs
@@ -424,7 +424,7 @@ namespace Umbraco.Tests.Persistence.Repositories
var repository = CreateRepository(unitOfWork);
// Act
- var exists = repository.Exists(1034); //Content picker
+ var exists = repository.Exists(1046); //Content picker
var doesntExist = repository.Exists(-80);
// Assert
@@ -481,12 +481,12 @@ namespace Umbraco.Tests.Persistence.Repositories
using (var unitOfWork = provider.CreateUnitOfWork())
{
var repository = Container.GetInstance(unitOfWork);
- dtd = new DataTypeDefinition(-1, Constants.PropertyEditors.RadioButtonListAlias) { Name = "test" };
+ dtd = new DataTypeDefinition(-1, Constants.PropertyEditors.RadioButtonListAlias) { Name = "test" };
repository.AddOrUpdate(dtd);
unitOfWork.Flush();
- unitOfWork.Database.Insert(new DataTypePreValueDto() { DataTypeNodeId = dtd.Id, SortOrder = 0, Value = "test1" });
- unitOfWork.Database.Insert(new DataTypePreValueDto() { DataTypeNodeId = dtd.Id, SortOrder = 1, Value = "test2" });
+ unitOfWork.Database.Insert(new DataTypePreValueDto { DataTypeNodeId = dtd.Id, SortOrder = 0, Value = "test1" });
+ unitOfWork.Database.Insert(new DataTypePreValueDto { DataTypeNodeId = dtd.Id, SortOrder = 1, Value = "test2" });
//this will cache the result
var collection = repository.GetPreValuesCollectionByDataTypeId(dtd.Id);
@@ -496,7 +496,7 @@ namespace Umbraco.Tests.Persistence.Repositories
var cache = CacheHelper.IsolatedRuntimeCache.GetCache();
Assert.IsTrue(cache);
var cached = cache.Result
- .GetCacheItemsByKeySearch(CacheKeys.DataTypePreValuesCacheKey + dtd.Id + "-");
+ .GetCacheItemsByKeySearch(CacheKeys.DataTypePreValuesCacheKey + "_" + dtd.Id);
Assert.IsNotNull(cached);
Assert.AreEqual(1, cached.Count());
@@ -527,7 +527,7 @@ namespace Umbraco.Tests.Persistence.Repositories
var cache = CacheHelper.IsolatedRuntimeCache.GetCache();
Assert.IsTrue(cache);
var cached = cache.Result
- .GetCacheItemsByKeySearch(CacheKeys.DataTypePreValuesCacheKey + dtd.Id + "-");
+ .GetCacheItemsByKeySearch(CacheKeys.DataTypePreValuesCacheKey + "_" + dtd.Id);
Assert.IsNotNull(cached);
Assert.AreEqual(1, cached.Count());
diff --git a/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs b/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs
index 359ead000b..05b7122154 100644
--- a/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs
+++ b/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs
@@ -6,13 +6,14 @@ using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Composing;
+using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.Testing;
namespace Umbraco.Tests.Persistence.Repositories
{
[TestFixture]
- [UmbracoTest(WithApplication = true)]
- public class PartialViewRepositoryTests : UmbracoTestBase
+ [UmbracoTest(WithApplication = true, Database = UmbracoTestOptions.Database.NewEmptyPerFixture)]
+ public class PartialViewRepositoryTests : TestWithDatabaseBase
{
private IFileSystem _fileSystem;
diff --git a/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs
index 289d4dfb03..e09253f996 100644
--- a/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs
+++ b/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs
@@ -231,6 +231,7 @@ namespace Umbraco.Tests.Persistence.Repositories
//now remove a few rules from a few of the items and then add some more, this will put things 'out of order' which
//we need to verify our sort order is working for the relator
+ // fixme - no "relator" in v8?!
for (int i = 0; i < allEntries.Count; i++)
{
//all the even ones
diff --git a/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs
index c5e5573e26..9d0d57fe98 100644
--- a/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs
+++ b/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs
@@ -10,13 +10,14 @@ using Umbraco.Core.Models;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.PropertyEditors;
+using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.Testing;
namespace Umbraco.Tests.Persistence.Repositories
{
[TestFixture]
- [UmbracoTest(WithApplication = true)]
- public class ScriptRepositoryTest : UmbracoTestBase
+ [UmbracoTest(WithApplication = true, Database = UmbracoTestOptions.Database.NewEmptyPerFixture)]
+ public class ScriptRepositoryTest : TestWithDatabaseBase
{
private IFileSystem _fileSystem;
diff --git a/src/Umbraco.Tests/Plugins/PluginManagerTests.cs b/src/Umbraco.Tests/Plugins/PluginManagerTests.cs
index f53d07eedd..5d3185fd16 100644
--- a/src/Umbraco.Tests/Plugins/PluginManagerTests.cs
+++ b/src/Umbraco.Tests/Plugins/PluginManagerTests.cs
@@ -147,6 +147,7 @@ namespace Umbraco.Tests.Plugins
public void Detect_Legacy_Plugin_File_List()
{
var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/PluginCache");
+ Directory.CreateDirectory(tempFolder);
var filePath= Path.Combine(tempFolder, string.Format("umbraco-plugins.{0}.list", NetworkHelper.FileSafeMachineName));
diff --git a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueConverterTests.cs b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueConverterTests.cs
index 71648fc480..863b2c7246 100644
--- a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueConverterTests.cs
+++ b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueConverterTests.cs
@@ -80,7 +80,8 @@ namespace Umbraco.Tests.PropertyEditors
public void CanConvertDropdownListMultiplePropertyEditor(object value, IEnumerable expected)
{
var converter = new DropdownListMultipleValueConverter();
- var result = converter.ConvertInterToObject(null, PropertyCacheLevel.Unknown, value, false);
+ var inter = converter.ConvertSourceToInter(null, value, false);
+ var result = converter.ConvertInterToObject(null, PropertyCacheLevel.Unknown, inter, false);
Assert.AreEqual(expected, result);
}
@@ -93,7 +94,8 @@ namespace Umbraco.Tests.PropertyEditors
public void CanConvertDropdownListMultipleWithKeysPropertyEditor(object value, IEnumerable expected)
{
var converter = new DropdownListMultipleWithKeysValueConverter();
- var result = converter.ConvertInterToObject(null, PropertyCacheLevel.Unknown, value, false);
+ var inter = converter.ConvertSourceToInter(null, value, false);
+ var result = converter.ConvertInterToObject(null, PropertyCacheLevel.Unknown, inter, false);
Assert.AreEqual(expected, result);
}
diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs
index f8c6e1f760..2a85d0f66f 100644
--- a/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs
+++ b/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs
@@ -23,6 +23,14 @@ namespace Umbraco.Tests.PublishedContent
// and http://msmvps.com/blogs/jon_skeet/archive/2010/10/28/overloading-and-generic-constraints.aspx
// and http://blogs.msdn.com/b/ericlippert/archive/2009/12/10/constraints-are-not-part-of-the-signature.aspx
+ public override void SetUp()
+ {
+ base.SetUp();
+
+ var umbracoContext = GetUmbracoContext();
+ Umbraco.Web.Composing.Current.UmbracoContextAccessor.UmbracoContext = umbracoContext;
+ }
+
protected override void Compose()
{
base.Compose();
@@ -42,7 +50,7 @@ namespace Umbraco.Tests.PublishedContent
return pluginManager;
}
- private void InitializeUmbracoContext()
+ private UmbracoContext GetUmbracoContext()
{
RouteData routeData = null;
@@ -59,7 +67,7 @@ namespace Umbraco.Tests.PublishedContent
TestObjects.GetUmbracoSettings(),
Enumerable.Empty());
- Umbraco.Web.Composing.Current.UmbracoContextAccessor.UmbracoContext = umbracoContext;
+ return umbracoContext;
}
public override void TearDown()
diff --git a/src/Umbraco.Tests/Routing/NiceUrlRoutesTests.cs b/src/Umbraco.Tests/Routing/NiceUrlRoutesTests.cs
index 411674dd02..343968419c 100644
--- a/src/Umbraco.Tests/Routing/NiceUrlRoutesTests.cs
+++ b/src/Umbraco.Tests/Routing/NiceUrlRoutesTests.cs
@@ -1,5 +1,6 @@
using System;
using NUnit.Framework;
+using Umbraco.Core.Models;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.Testing;
using Umbraco.Web.PublishedCache.XmlPublishedCache;
@@ -48,6 +49,14 @@ namespace Umbraco.Tests.Routing
";
}
+ protected override void Initialize()
+ {
+ base.Initialize();
+
+ if (FirstTestInFixture)
+ ServiceContext.ContentTypeService.Save(new ContentType(-1) { Alias = "Doc", Name = "name" });
+ }
+
#endregion
/*
@@ -181,6 +190,19 @@ DetermineRouteById(id):
[TestCase(2004, false, "/x/b")]
[TestCase(2005, false, "/x/b/c")]
[TestCase(2006, false, "/x/b/e")]
+ public void GetRouteByIdNoHide(int id, bool hide, string expected)
+ {
+ var umbracoContext = GetUmbracoContext("/test", 0);
+ var cache = umbracoContext.ContentCache as PublishedContentCache;
+ if (cache == null) throw new Exception("Unsupported IPublishedContentCache, only the Xml one is supported.");
+
+ SettingsForTests.HideTopLevelNodeFromPath = hide;
+
+ const bool preview = true; // make sure we don't cache
+ var route = cache.GetRouteById(preview, id);
+ Assert.AreEqual(expected, route);
+ }
+
[TestCase(1000, true, "/")]
[TestCase(1001, true, "/b")]
[TestCase(1002, true, "/b/c")]
@@ -192,7 +214,7 @@ DetermineRouteById(id):
[TestCase(2004, true, "/b")] // collision!
[TestCase(2005, true, "/b/c")] // collision!
[TestCase(2006, true, "/b/e")] // risky!
- public void GetRouteById(int id, bool hide, string expected)
+ public void GetRouteByIdHide(int id, bool hide, string expected)
{
var umbracoContext = GetUmbracoContext("/test", 0);
var cache = umbracoContext.ContentCache as PublishedContentCache;
@@ -214,10 +236,7 @@ DetermineRouteById(id):
SettingsForTests.HideTopLevelNodeFromPath = false;
- // make sure we cache
- const bool preview = false;
-
- var route = cache.GetRouteById(preview, 1000);
+ var route = cache.GetRouteById(false, 1000);
Assert.AreEqual("/a", route);
// GetRouteById registers a non-trusted route, which is cached for
@@ -239,6 +258,27 @@ DetermineRouteById(id):
[TestCase("/a/b/c", false, 1002)]
[TestCase("/a/b/c/d", false, 1003)]
[TestCase("/x", false, 2000)]
+ public void GetByRouteNoHide(string route, bool hide, int expected)
+ {
+ var umbracoContext = GetUmbracoContext("/test", 0);
+ var cache = umbracoContext.ContentCache as PublishedContentCache;
+ if (cache == null) throw new Exception("Unsupported IPublishedContentCache, only the Xml one is supported.");
+
+ SettingsForTests.HideTopLevelNodeFromPath = hide;
+
+ const bool preview = false; // make sure we don't cache - but HOW? should be some sort of switch?!
+ var content = cache.GetByRoute(preview, route);
+ if (expected < 0)
+ {
+ Assert.IsNull(content);
+ }
+ else
+ {
+ Assert.IsNotNull(content);
+ Assert.AreEqual(expected, content.Id);
+ }
+ }
+
[TestCase("/", true, 1000)]
[TestCase("/a", true, 2003)]
[TestCase("/a/b", true, -1)]
@@ -248,7 +288,7 @@ DetermineRouteById(id):
[TestCase("/y/z", true, 2002)]
[TestCase("/b", true, 1001)] // (hence the 2004 collision)
[TestCase("/b/c", true, 1002)] // (hence the 2005 collision)
- public void GetByRoute(string route, bool hide, int expected)
+ public void GetByRouteHide(string route, bool hide, int expected)
{
var umbracoContext = GetUmbracoContext("/test", 0);
var cache = umbracoContext.ContentCache as PublishedContentCache;
@@ -256,7 +296,7 @@ DetermineRouteById(id):
SettingsForTests.HideTopLevelNodeFromPath = hide;
- const bool preview = true; // make sure we don't cache
+ const bool preview = false; // make sure we don't cache - but HOW? should be some sort of switch?!
var content = cache.GetByRoute(preview, route);
if (expected < 0)
{
@@ -278,10 +318,7 @@ DetermineRouteById(id):
SettingsForTests.HideTopLevelNodeFromPath = false;
- // make sure we cache
- const bool preview = false;
-
- var content = cache.GetByRoute(preview, "/a/b/c");
+ var content = cache.GetByRoute(false, "/a/b/c");
Assert.IsNotNull(content);
Assert.AreEqual(1002, content.Id);
diff --git a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs
index 64a5b48d55..a1ea644a45 100644
--- a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs
+++ b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs
@@ -1,22 +1,25 @@
using System;
-using System.Collections.Generic;
using System.Linq;
+using LightInject;
using Moq;
using NUnit.Framework;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
-using Umbraco.Core.Persistence;
using Umbraco.Core.Scoping;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.Entities;
+using Umbraco.Core.Composing;
+using Umbraco.Core.Persistence.Mappers;
namespace Umbraco.Tests.Scoping
{
[TestFixture]
public class ScopeEventDispatcherTests //: BaseUmbracoConfigurationTest
{
+ private TestObjects _testObjects;
+
[SetUp]
public void Setup()
{
@@ -24,6 +27,23 @@ namespace Umbraco.Tests.Scoping
DoThing1 = null;
DoThing2 = null;
DoThing3 = null;
+
+ Current.Container = new ServiceContainer();
+
+ _testObjects = new TestObjects(Current.Container);
+ Current.Container.RegisterSingleton(f => Current.Container);
+ Current.Container.RegisterSingleton(factory => new FileSystems(factory.TryGetInstance()));
+ Current.Container.RegisterCollectionBuilder();
+
+ SettingsForTests.Reset(); // ensure we have configuration
+ }
+
+ [TearDown]
+ public void TearDown()
+ {
+ Current.Reset();
+
+ SettingsForTests.Reset();
}
[TestCase(false, true, true)]
@@ -42,7 +62,7 @@ namespace Umbraco.Tests.Scoping
DoThing1 += (sender, args) => { counter1++; if (cancel) args.Cancel = true; };
DoThing2 += (sender, args) => { counter2++; };
- var scopeProvider = new ScopeProvider(Mock.Of(), Mock.Of(), Mock.Of());
+ var scopeProvider = _testObjects.GetScopeProvider(Mock.Of());
using (var scope = scopeProvider.CreateScope(eventDispatcher: passive ? new PassiveEventDispatcher() : null))
{
var cancelled = scope.Events.DispatchCancelable(DoThing1, this, new SaveEventArgs("test"));
@@ -71,7 +91,7 @@ namespace Umbraco.Tests.Scoping
DoThing2 += OnDoThingFail;
DoThing3 += OnDoThingFail;
- var scopeProvider = new ScopeProvider(Mock.Of(), Mock.Of(), Mock.Of());
+ var scopeProvider = _testObjects.GetScopeProvider(Mock.Of());
using (var scope = scopeProvider.CreateScope(eventDispatcher: new PassiveEventDispatcher()))
{
scope.Events.Dispatch(DoThing1, this, new SaveEventArgs("test"));
@@ -101,7 +121,7 @@ namespace Umbraco.Tests.Scoping
DoDeleteForContent += OnDoThingFail;
DoForTestArgs += OnDoThingFail;
DoForTestArgs2 += OnDoThingFail;
-
+
var contentType = MockedContentTypes.CreateBasicContentType();
var content1 = MockedContent.CreateBasicContent(contentType);
@@ -113,10 +133,10 @@ namespace Umbraco.Tests.Scoping
var content3 = MockedContent.CreateBasicContent(contentType);
content3.Id = 789;
- var scopeProvider = new ScopeProvider(Mock.Of(), Mock.Of(), Mock.Of());
+ var scopeProvider = _testObjects.GetScopeProvider(Mock.Of());
using (var scope = scopeProvider.CreateScope(eventDispatcher: new PassiveEventDispatcher()))
{
-
+
//content1 will be filtered from the args
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs(new[]{ content1 , content3}));
scope.Events.Dispatch(DoDeleteForContent, this, new DeleteEventArgs(content1));
@@ -145,13 +165,13 @@ namespace Umbraco.Tests.Scoping
///
/// This will test that when we track events that before we Get the events we normalize all of the
- /// event entities to be the latest one (most current) found amongst the event so that there is
+ /// event entities to be the latest one (most current) found amongst the event so that there is
/// no 'stale' entities in any of the args
///
[Test]
public void LatestEntities()
{
- DoSaveForContent += OnDoThingFail;
+ DoSaveForContent += OnDoThingFail;
var now = DateTime.Now;
var contentType = MockedContentTypes.CreateBasicContentType();
@@ -165,9 +185,9 @@ namespace Umbraco.Tests.Scoping
content3.Id = 123;
content3.UpdateDate = now.AddMinutes(3);
- var scopeProvider = new ScopeProvider(Mock.Of(), Mock.Of(), Mock.Of());
+ var scopeProvider = _testObjects.GetScopeProvider(Mock.Of());
using (var scope = scopeProvider.CreateScope(eventDispatcher: new PassiveEventDispatcher()))
- {
+ {
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs(content1));
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs(content2));
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs(content3));
@@ -175,7 +195,7 @@ namespace Umbraco.Tests.Scoping
// events have been queued
var events = scope.Events.GetEvents(EventDefinitionFilter.All).ToArray();
Assert.AreEqual(3, events.Length);
-
+
foreach (var t in events)
{
var args = (SaveEventArgs)t.Args;
@@ -205,7 +225,7 @@ namespace Umbraco.Tests.Scoping
content3.Id = 123;
content1.UpdateDate = now.AddMinutes(3);
- var scopeProvider = new ScopeProvider(Mock.Of(), Mock.Of(), Mock.Of());
+ var scopeProvider = _testObjects.GetScopeProvider(Mock.Of());
using (var scope = scopeProvider.CreateScope(eventDispatcher: new PassiveEventDispatcher()))
{
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs(content1));
@@ -214,7 +234,7 @@ namespace Umbraco.Tests.Scoping
// events have been queued
var events = scope.Events.GetEvents(EventDefinitionFilter.FirstIn).ToArray();
- Assert.AreEqual(1, events.Length);
+ Assert.AreEqual(1, events.Length);
Assert.AreEqual(content1, ((SaveEventArgs) events[0].Args).SavedEntities.First());
Assert.IsTrue(object.ReferenceEquals(content1, ((SaveEventArgs)events[0].Args).SavedEntities.First()));
Assert.AreEqual(content1.UpdateDate, ((SaveEventArgs) events[0].Args).SavedEntities.First().UpdateDate);
@@ -238,7 +258,7 @@ namespace Umbraco.Tests.Scoping
content3.Id = 123;
content3.UpdateDate = now.AddMinutes(3);
- var scopeProvider = new ScopeProvider(Mock.Of(), Mock.Of(), Mock.Of());
+ var scopeProvider = _testObjects.GetScopeProvider(Mock.Of());
using (var scope = scopeProvider.CreateScope(eventDispatcher: new PassiveEventDispatcher()))
{
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs(content1));
@@ -262,7 +282,7 @@ namespace Umbraco.Tests.Scoping
DoThing2 += OnDoThingFail;
DoThing3 += OnDoThingFail;
- var scopeProvider = new ScopeProvider(Mock.Of(), Mock.Of(), Mock.Of());
+ var scopeProvider = _testObjects.GetScopeProvider(Mock.Of());
using (var scope = scopeProvider.CreateScope(eventDispatcher: new PassiveEventDispatcher()))
{
scope.Events.Dispatch(DoThing1, this, new SaveEventArgs("test"));
@@ -288,7 +308,7 @@ namespace Umbraco.Tests.Scoping
ScopeContext ambientContext = null;
Guid value = Guid.Empty;
- var scopeProvider = new ScopeProvider(Mock.Of(), Mock.Of(), Mock.Of());
+ var scopeProvider = _testObjects.GetScopeProvider(Mock.Of()) as ScopeProvider;
DoThing1 += (sender, args) => { counter++; };
DoThing2 += (sender, args) => { counter++; };
diff --git a/src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs b/src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs
index aa3bd3dd05..ae16ba484f 100644
--- a/src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs
+++ b/src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs
@@ -27,6 +27,7 @@ namespace Umbraco.Tests.Scoping
{
base.TearDown();
SafeCallContext.Clear();
+ ShadowFileSystems.ResetId();
ClearFiles();
}
diff --git a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs
index f3efe56a2c..8bce82e67c 100644
--- a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs
+++ b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs
@@ -1,6 +1,8 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
+using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
@@ -8,6 +10,10 @@ using Umbraco.Core.Scoping;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.Testing;
using Umbraco.Web.Cache;
+using LightInject;
+using Moq;
+using Umbraco.Core.Events;
+using Umbraco.Core.Sync;
namespace Umbraco.Tests.Scoping
{
@@ -17,6 +23,32 @@ namespace Umbraco.Tests.Scoping
{
private CacheRefresherComponent _cacheRefresher;
+ protected override void Compose()
+ {
+ base.Compose();
+
+ // the cache refresher component needs to trigger to refresh caches
+ // but then, it requires a lot of plumbing ;(
+ // fixme - and we cannot inject a DistributedCache yet
+ // so doing all this mess
+ Container.RegisterSingleton();
+ Container.RegisterSingleton(f => Mock.Of());
+ Container.RegisterCollectionBuilder()
+ .Add(f => f.TryGetInstance().GetCacheRefreshers());
+ }
+
+ protected override void ComposeCacheHelper()
+ {
+ // this is what's created core web runtime
+ var cacheHelper = new CacheHelper(
+ new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()),
+ new StaticCacheProvider(),
+ new NullCacheProvider(),
+ new IsolatedRuntimeCache(type => new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider())));
+ Container.RegisterSingleton(f => cacheHelper);
+ Container.RegisterSingleton(f => f.GetInstance().RuntimeCache);
+ }
+
[TearDown]
public void Teardown()
{
@@ -42,13 +74,16 @@ namespace Umbraco.Tests.Scoping
Assert.AreEqual(user.Id, globalCached.Id);
Assert.AreEqual("name", globalCached.Name);
+ // get user again - else we'd modify the one that's in the cache
+ user = service.GetUserById(user.Id);
+
_cacheRefresher = new CacheRefresherComponent(true);
_cacheRefresher.Initialize();
Assert.IsNull(scopeProvider.AmbientScope);
using (var scope = scopeProvider.CreateScope(repositoryCacheMode: RepositoryCacheMode.Scoped))
{
- Assert.IsInstanceOf(scope);
+ Assert.IsInstanceOf(scope);
Assert.IsNotNull(scopeProvider.AmbientScope);
Assert.AreSame(scope, scopeProvider.AmbientScope);
@@ -76,7 +111,7 @@ namespace Umbraco.Tests.Scoping
}
Assert.IsNull(scopeProvider.AmbientScope);
- globalCached = (IUser)globalCache.GetCacheItem(GetCacheIdKey(user.Id), () => null);
+ globalCached = (IUser) globalCache.GetCacheItem(GetCacheIdKey(user.Id), () => null);
if (complete)
{
// global cache has been cleared
@@ -129,7 +164,7 @@ namespace Umbraco.Tests.Scoping
Assert.IsNull(scopeProvider.AmbientScope);
using (var scope = scopeProvider.CreateScope(repositoryCacheMode: RepositoryCacheMode.Scoped))
{
- Assert.IsInstanceOf(scope);
+ Assert.IsInstanceOf(scope);
Assert.IsNotNull(scopeProvider.AmbientScope);
Assert.AreSame(scope, scopeProvider.AmbientScope);
@@ -221,7 +256,7 @@ namespace Umbraco.Tests.Scoping
Assert.IsNull(scopeProvider.AmbientScope);
using (var scope = scopeProvider.CreateScope(repositoryCacheMode: RepositoryCacheMode.Scoped))
{
- Assert.IsInstanceOf(scope);
+ Assert.IsInstanceOf(scope);
Assert.IsNotNull(scopeProvider.AmbientScope);
Assert.AreSame(scope, scopeProvider.AmbientScope);
@@ -281,5 +316,29 @@ namespace Umbraco.Tests.Scoping
{
return $"uRepo_{typeof (T).Name}_";
}
+
+ public class PassiveEventDispatcher : QueuingEventDispatcherBase
+ {
+ public PassiveEventDispatcher()
+ : base(false)
+ { }
+
+ protected override void ScopeExitCompleted()
+ {
+ // do nothing
+ }
+ }
+
+ public class LocalServerMessenger : ServerMessengerBase
+ {
+ public LocalServerMessenger()
+ : base(false)
+ { }
+
+ protected override void DeliverRemote(IEnumerable servers, ICacheRefresher refresher, MessageType messageType, IEnumerable