Skip to content

Commit

Permalink
MarimerLLC#4015 Fix recursion issue and add unit tests (MarimerLLC#4043)
Browse files Browse the repository at this point in the history
* MarimerLLC#4015 Fix recursion issue and add unit tests

* MarimerLLC#4015 update for code review comment

* MarimerLLC#4015 change to use resources for strings.

* MarimerLLC#4015 Simplified syntax

---------

Co-authored-by: Rockford Lhotka <[email protected]>
  • Loading branch information
Bowman74 and rockfordlhotka authored Jun 18, 2024
1 parent d701e9a commit d6069d4
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 18 deletions.
74 changes: 74 additions & 0 deletions Source/Csla.test/AppContext/AppContextTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
//-----------------------------------------------------------------------

using Csla.Configuration;
using Csla.Core;
using Csla.TestHelpers;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Csla.Test.AppContext
Expand Down Expand Up @@ -89,6 +91,78 @@ public void ClientContext()
Assert.AreEqual("new global value", TestResults.GetResult("globalcontext"), "New global value lost");
}

/// <summary>
/// Tests the addition of a key-value pair to the ContextDictionary.
/// This method verifies that a new key-value pair can be successfully added
/// and subsequently retrieved from the ContextDictionary, ensuring the dictionary's
/// add functionality works as expected.
/// </summary>
[TestMethod]
public void ContextDictionaryAdd()
{
var contextDectionary = new ContextDictionary();
string key = "key1";
string value = "value1";

contextDectionary.Add(key, value);

Assert.AreEqual(value, contextDectionary[key]);
}

/// <summary>
/// Tests that adding a duplicate key to the ContextDictionary throws the correct exception.
/// This method verifies that the ContextDictionary enforces unique keys by attempting to add
/// a key-value pair where the key already exists in the dictionary. The expected behavior is
/// that an ArgumentException is thrown, indicating the key's presence and preventing the addition.
/// </summary>
[TestMethod]
public void ContextDictionaryAddThrowsCorrectException()
{
var contextDectionary = new ContextDictionary();
string key = "key1";
string value = "value1";

contextDectionary[key] = value;

Assert.ThrowsException<System.ArgumentException>(() => contextDectionary.Add(key, value));
}

/// <summary>
/// Tests the removal of a key-value pair from the ContextDictionary.
/// This method verifies that a key-value pair can be successfully removed from the ContextDictionary,
/// ensuring the dictionary's remove functionality works as expected. It adds a key-value pair, removes it,
/// and then checks that the key no longer exists in the dictionary.
/// </summary>
[TestMethod]
public void ContextDictionaryRemove()
{
var contextDectionary = new ContextDictionary();
string key = "key1";
string value = "value1";


contextDectionary[key] = value;
contextDectionary.Remove(key);

Assert.IsFalse(contextDectionary.ContainsKey(key));
}

/// <summary>
/// Tests that attempting to remove a non-existent key from the ContextDictionary throws the correct exception.
/// This method verifies the dictionary's behavior when a removal operation is attempted for a key that does not exist.
/// The expected behavior is that a NotSupportedException is thrown, indicating that the operation is not supported
/// for keys that are not present in the dictionary.
/// </summary>
[TestMethod]
public void ContextDictionaryRemoveThrowsCorrectException()
{
var contextDectionary = new ContextDictionary();
string key = "key1";
string value = "value1";

Assert.ThrowsException<System.NotSupportedException>(() => contextDectionary.Remove(key));
}

#endregion

#region FailCreateContext
Expand Down
10 changes: 5 additions & 5 deletions Source/Csla.test/AppContext/TestContextManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Csla.Test.AppContext
public class TestContextManager : IContextManager
{
[ThreadStatic]
private static HybridDictionary _myContext = [];
private static IContextDictionary _myContext = new ContextDictionary();
private readonly AsyncLocal<IPrincipal> _principal = new();

private const string _localContextName = "Csla.ClientContext";
Expand Down Expand Up @@ -43,7 +43,7 @@ public IContextDictionary GetLocalContext()
{
if (_myContext[_localContextName] == null)
SetLocalContext(new ContextDictionary());
return (ContextDictionary)_myContext[_localContextName];
return (IContextDictionary)_myContext[_localContextName];
}

public void SetLocalContext(IContextDictionary localContext)
Expand All @@ -55,22 +55,22 @@ public IContextDictionary GetClientContext(ApplicationContext.ExecutionLocations
{
if (_myContext[_clientContextName] == null)
SetClientContext(new ContextDictionary(), executionLocation);
return (ContextDictionary) _myContext[_clientContextName];
return (IContextDictionary) _myContext[_clientContextName];
}

public void SetClientContext(IContextDictionary clientContext, ApplicationContext.ExecutionLocations executionLocation)
{
_myContext[_clientContextName] = clientContext;
}

public ContextDictionary GetGlobalContext()
public IContextDictionary GetGlobalContext()
{
if (_myContext[_globalContextName] == null)
SetGlobalContext(new ContextDictionary());
return (ContextDictionary)_myContext[_globalContextName];
}

public void SetGlobalContext(ContextDictionary globalContext)
public void SetGlobalContext(IContextDictionary globalContext)
{
_myContext[_globalContextName] = globalContext;
}
Expand Down
29 changes: 16 additions & 13 deletions Source/Csla/Core/ContextDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
// <summary>Dictionary type that is serializable</summary>
//-----------------------------------------------------------------------

using Csla.Properties;
using Csla.Serialization.Mobile;
using System.Collections;
using System.Collections.Concurrent;

namespace Csla.Core
Expand Down Expand Up @@ -76,25 +76,33 @@ void IMobileObject.SetChildren(SerializationInfo info, MobileFormatter formatter
/// <inheritdoc cref="System.Collections.IDictionary.IsReadOnly"/>
public bool IsReadOnly
{
get => ((IDictionary)this).IsReadOnly;
get => false;
}

/// <inheritdoc cref="System.Collections.IDictionary.IsFixedSize"/>
public bool IsFixedSize
{
get => ((IDictionary)this).IsFixedSize;
get => false;
}

/// <inheritdoc cref="System.Collections.IDictionary.Add(object, object?)"/>
public void Add(object key, object value)
{
((IDictionary)this).Add(key, value);
bool added = TryAdd(key, value);
if (!added)
{
throw new ArgumentException(Resources.KeyAlreadyExistsException);
}
}

/// <inheritdoc cref="System.Collections.IDictionary.Remove(object)"/>
public void Remove(object key)
{
((IDictionary)this).Remove(key);
var removed = TryRemove(key, out var _);
if (!removed)
{
throw new NotSupportedException(Resources.KeyDoesNotExistException);
}
}

#endregion
Expand All @@ -104,19 +112,14 @@ public void Remove(object key)
/// <inheritdoc cref="System.Collections.ICollection.SyncRoot"/>
public object SyncRoot
{
get => ((IDictionary)this).SyncRoot;
get => throw new NotSupportedException(Resources.SyncrootNotSupportedException);

}

/// <inheritdoc cref="System.Collections.ICollection.IsSynchronized"/>
public bool IsSynchronized
{
get => ((ICollection)this).IsSynchronized;
}

/// <inheritdoc cref="System.Collections.ICollection.CopyTo(Array, int)"/>
public void CopyTo(Array array, int index)
{
((ICollection)this).CopyTo(array, index);
get => false;
}

#endregion
Expand Down
27 changes: 27 additions & 0 deletions Source/Csla/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions Source/Csla/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
Expand Down Expand Up @@ -485,4 +490,13 @@
<data name="StringNotNullOrWhiteSpaceException" xml:space="preserve">
<value>{0} must not be null, empty or only consisting of white spaces.</value>
</data>
<data name="KeyAlreadyExistsException" xml:space="preserve">
<value>An element with the same key already exists in the dictionary object.</value>
</data>
<data name="KeyDoesNotExistException" xml:space="preserve">
<value>Key is null.</value>
</data>
<data name="SyncrootNotSupportedException" xml:space="preserve">
<value>SyncRoot NotSupported</value>
</data>
</root>

0 comments on commit d6069d4

Please sign in to comment.