-
-
Notifications
You must be signed in to change notification settings - Fork 406
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add custom serializers to MobileFormatter (#4024)
* #2531 Initial changes to implement IMobileSerializer concept * #2531 Maintain Serialization configuration for custom formatters * Use modern namespace technique * Fix comment * #2531 Initial implementation of deserialization * Resolve build warning * #2531 Rework how mobile formatter config works * #2531 Custom serializer now works with ClaimsPrincipal * #2531 Remove obsolete CslaClaimsPrincipal type * Clean up ctor and application context * #2531 Put ClaimsPrincipalSerializer into core framework * #2531 Add custom serializer tests * #2531 Updates based on PR feedback * Fix comments * #2531 Move serialzation formatter config to be instance not static * Clean up what were static methods to work correctly now * #2531 Allow unknown types to fall through FieldDataManager as "children" * #2531 Ensure native types are handled correctly * #2531 Update tests * #2531 Use a func to determine if a type can be handled by a serializer * #2531 Add test using CanSerialize * #2531 Rework TypeMap to use generics for type safety and readability * #3363 Add test for DateTime.Kind serialization * #1877 Add implementation of ClaimsPrincipal serialization for .NET Framework * Fix build warning * #2148 Add Json-based PocoSerializer for simple types * #2531 Update method name * #2531 Add and use MobileFormatterException * #2531 Update implementation and property scopes * #2531 Make type internal * Update tests * #2531 Use DI to get the ISerializationFormatter service * #2531 Remove SerializationFormatterFactory type * #2531 Remove OriginalType * Remove commented code * #2531 Clean up code * #2531 Fix expected exception type * Remove obsolete compiler conditionals * #3871 Updated release notes * Add `dev/` prefix to working branch names * #2531 Code cleanup and improvement based on PR review * #2531 Make MobileFormatterOptions a service
- Loading branch information
1 parent
018f366
commit 1f16f6b
Showing
49 changed files
with
1,044 additions
and
654 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
282 changes: 121 additions & 161 deletions
282
Source/Csla.Blazor.WebAssembly.Tests/SessionManagerTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,196 +1,156 @@ | ||
//----------------------------------------------------------------------- | ||
// <copyright file="SessionManagerTests.cs" company="Marimer LLC"> | ||
// Copyright (c) Marimer LLC. All rights reserved. | ||
// Website: https://cslanet.com | ||
// </copyright> | ||
// <summary>no summary</summary> | ||
//----------------------------------------------------------------------- | ||
|
||
using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
using Csla.Blazor.WebAssembly.State; | ||
using Csla.State; | ||
using Csla.Blazor.WebAssembly.Configuration; | ||
using Csla.Core; | ||
using Csla.Runtime; | ||
using System.Net; | ||
using Csla.Serialization; | ||
using Csla.Serialization.Mobile; | ||
using Microsoft.AspNetCore.Components.Authorization; | ||
using NSubstitute; | ||
using System.Security.Claims; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Csla.Configuration; | ||
|
||
namespace Csla.Test.State; | ||
|
||
namespace Csla.Test.State | ||
[TestClass] | ||
public class SessionManagerTests | ||
{ | ||
[TestClass] | ||
public class SessionManagerTests | ||
private SessionManager _sessionManager; | ||
private SessionMessage _sessionValue; | ||
|
||
[TestInitialize] | ||
public void Initialize() | ||
{ | ||
private SessionManager _sessionManager; | ||
private SessionMessage _sessionValue; | ||
var services = new ServiceCollection(); | ||
services.AddCsla(o => o.AddBlazorWebAssembly()); | ||
var provider = services.BuildServiceProvider(); | ||
var _applicationContext = provider.GetRequiredService<ApplicationContext>(); | ||
|
||
[TestInitialize] | ||
public void Initialize() | ||
_sessionValue = new SessionMessage | ||
{ | ||
var mockServiceProvider = Substitute.For<IServiceProvider>(); | ||
|
||
// Mock AuthenticationStateProvider | ||
var mockAuthStateProvider = Substitute.For<AuthenticationStateProvider>(); | ||
|
||
// Mock IServiceProvider | ||
mockServiceProvider.GetService(typeof(AuthenticationStateProvider)).Returns(mockAuthStateProvider); | ||
|
||
_sessionValue = new SessionMessage | ||
{ | ||
// Set properties here | ||
// For example: | ||
Principal = new Security.CslaClaimsPrincipal() { }, | ||
Session = [] | ||
}; | ||
|
||
// Mock ISerializationFormatter | ||
var mockFormatter = Substitute.For<ISerializationFormatter>(); | ||
mockFormatter.Serialize(Arg.Any<Stream>(), Arg.Any<object>()); | ||
mockFormatter.Deserialize(Arg.Any<Stream>()).Returns(_sessionValue); | ||
|
||
// Mock IServiceProvider | ||
mockServiceProvider.GetService(typeof(MobileFormatter)).Returns(mockFormatter); | ||
|
||
var mockActivator = Substitute.For<Server.IDataPortalActivator>(); | ||
mockActivator.CreateInstance(Arg.Is<Type>(t => t == typeof(MobileFormatter))).Returns(mockFormatter); | ||
mockActivator.InitializeInstance(Arg.Any<object>()); | ||
|
||
// Mock IServiceProvider | ||
mockServiceProvider.GetService(typeof(Server.IDataPortalActivator)).Returns(mockActivator); | ||
|
||
// Mock IContextManager | ||
var mockContextManager = Substitute.For<IContextManager>(); | ||
mockContextManager.IsValid.Returns(true); | ||
|
||
// Mock IContextManagerLocal | ||
var mockLocalContextManager = Substitute.For<IContextManagerLocal>(); | ||
|
||
// Mock IServiceProvider | ||
mockServiceProvider.GetService(typeof(IRuntimeInfo)).Returns(new RuntimeInfo()); | ||
|
||
// Mock IEnumerable<IContextManager> | ||
var mockContextManagerList = new List<IContextManager> { mockContextManager }; | ||
|
||
// Mock ApplicationContextAccessor | ||
var mockApplicationContextAccessor = Substitute.For<ApplicationContextAccessor>(mockContextManagerList, mockLocalContextManager, mockServiceProvider); | ||
|
||
var _applicationContext = new ApplicationContext(mockApplicationContextAccessor); | ||
Principal = new ClaimsPrincipal() { }, | ||
Session = [] | ||
}; | ||
|
||
_sessionManager = new SessionManager(_applicationContext, GetHttpClient(_sessionValue, _applicationContext), new BlazorWebAssemblyConfigurationOptions { SyncContextWithServer = true }); | ||
} | ||
_sessionManager = new SessionManager(_applicationContext, GetHttpClient(_sessionValue, _applicationContext), new BlazorWebAssemblyConfigurationOptions { SyncContextWithServer = true }); | ||
} | ||
|
||
public class TestHttpMessageHandler(SessionMessage session, ApplicationContext _applicationContext) : HttpMessageHandler | ||
{ | ||
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) | ||
{ | ||
cancellationToken.ThrowIfCancellationRequested(); | ||
var response = new HttpResponseMessage() | ||
{ | ||
StatusCode = HttpStatusCode.OK, | ||
Content = new StringContent("{\"ResultStatus\":0, \"SessionData\":\"" + Convert.ToBase64String(GetSession(session, _applicationContext)) + "\"}"), | ||
}; | ||
return Task.FromResult(response); | ||
} | ||
} | ||
private static HttpClient GetHttpClient(SessionMessage session, ApplicationContext _applicationContext) | ||
public class TestHttpMessageHandler(SessionMessage session, ApplicationContext _applicationContext) : HttpMessageHandler | ||
{ | ||
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) | ||
{ | ||
var handlerMock = new TestHttpMessageHandler(session,_applicationContext); | ||
// use real http client with mocked handler here | ||
var httpClient = new HttpClient(handlerMock) | ||
cancellationToken.ThrowIfCancellationRequested(); | ||
var response = new HttpResponseMessage() | ||
{ | ||
BaseAddress = new Uri("http://test.com/"), | ||
StatusCode = HttpStatusCode.OK, | ||
Content = new StringContent("{\"ResultStatus\":0, \"SessionData\":\"" + Convert.ToBase64String(GetSession(session, _applicationContext)) + "\"}"), | ||
}; | ||
return httpClient; | ||
return Task.FromResult(response); | ||
} | ||
|
||
private static byte[] GetSession(SessionMessage session, ApplicationContext _applicationContext) | ||
} | ||
private static HttpClient GetHttpClient(SessionMessage session, ApplicationContext _applicationContext) | ||
{ | ||
var handlerMock = new TestHttpMessageHandler(session,_applicationContext); | ||
// use real http client with mocked handler here | ||
var httpClient = new HttpClient(handlerMock) | ||
{ | ||
var info = new MobileFormatter(_applicationContext).SerializeToDTO(session); | ||
var ms = new MemoryStream(); | ||
new CslaBinaryWriter(_applicationContext).Write(ms, info); | ||
ms.Position = 0; | ||
var array = ms.ToArray(); | ||
return array; | ||
} | ||
BaseAddress = new Uri("http://test.com/"), | ||
}; | ||
return httpClient; | ||
} | ||
|
||
[TestMethod] | ||
public async Task RetrieveSession_WithTimeoutValue_ShouldNotThrowException() | ||
{ | ||
var timeout = TimeSpan.FromHours(1); | ||
var session = await _sessionManager.RetrieveSession(timeout); | ||
Assert.AreEqual(session, _sessionValue.Session); | ||
} | ||
private static byte[] GetSession(SessionMessage session, ApplicationContext _applicationContext) | ||
{ | ||
return new MobileFormatter(_applicationContext).SerializeToByteArray(session); | ||
} | ||
|
||
[TestMethod] | ||
public async Task RetrieveSession_WithZeroTimeout_ShouldThrowTimeoutException() | ||
{ | ||
var timeout = TimeSpan.Zero; | ||
await Assert.ThrowsExceptionAsync<TimeoutException>(() => _sessionManager.RetrieveSession(timeout)); | ||
} | ||
[TestMethod] | ||
public async Task RetrieveSession_WithTimeoutValue_ShouldNotThrowException() | ||
{ | ||
var timeout = TimeSpan.FromHours(1); | ||
var session = await _sessionManager.RetrieveSession(timeout); | ||
} | ||
|
||
[TestMethod] | ||
public async Task RetrieveSession_WithValidCancellationToken_ShouldNotThrowException() | ||
{ | ||
var cts = new CancellationTokenSource(); | ||
var session = await _sessionManager.RetrieveSession(cts.Token); | ||
Assert.AreEqual(session, _sessionValue.Session); | ||
} | ||
[TestMethod] | ||
public async Task RetrieveSession_WithZeroTimeout_ShouldThrowTimeoutException() | ||
{ | ||
var timeout = TimeSpan.Zero; | ||
await Assert.ThrowsExceptionAsync<TimeoutException>(() => _sessionManager.RetrieveSession(timeout)); | ||
} | ||
|
||
[TestMethod] | ||
public async Task RetrieveSession_WithCancelledCancellationToken_ShouldThrowTaskCanceledException() | ||
{ | ||
var cts = new CancellationTokenSource(); | ||
cts.Cancel(); | ||
await Assert.ThrowsExceptionAsync<TaskCanceledException>(() => _sessionManager.RetrieveSession(cts.Token)); | ||
} | ||
[TestMethod] | ||
public async Task RetrieveSession_WithValidCancellationToken_ShouldNotThrowException() | ||
{ | ||
var cts = new CancellationTokenSource(); | ||
var session = await _sessionManager.RetrieveSession(cts.Token); | ||
} | ||
|
||
[TestMethod] | ||
public async Task SendSession_WithTimeoutValue_ShouldNotThrowException() | ||
{ | ||
await _sessionManager.RetrieveSession(TimeSpan.FromHours(1)); | ||
[TestMethod] | ||
public async Task RetrieveSession_WithCancelledCancellationToken_ShouldThrowTaskCanceledException() | ||
{ | ||
var cts = new CancellationTokenSource(); | ||
cts.Cancel(); | ||
await Assert.ThrowsExceptionAsync<TaskCanceledException>(() => _sessionManager.RetrieveSession(cts.Token)); | ||
} | ||
|
||
var timeout = TimeSpan.FromHours(1); | ||
await _sessionManager.SendSession(timeout); | ||
Assert.IsTrue(true); | ||
} | ||
[TestMethod] | ||
public async Task SendSession_WithTimeoutValue_ShouldNotThrowException() | ||
{ | ||
await _sessionManager.RetrieveSession(TimeSpan.FromHours(1)); | ||
|
||
[TestMethod] | ||
public async Task SendSession_WithZeroTimeout_ShouldThrowTimeoutException() | ||
{ | ||
await _sessionManager.RetrieveSession(TimeSpan.FromHours(1)); | ||
var timeout = TimeSpan.FromHours(1); | ||
await _sessionManager.SendSession(timeout); | ||
Assert.IsTrue(true); | ||
} | ||
|
||
var timeout = TimeSpan.Zero; | ||
await Assert.ThrowsExceptionAsync<TimeoutException>(() => _sessionManager.SendSession(timeout)); | ||
} | ||
[TestMethod] | ||
public async Task SendSession_WithZeroTimeout_ShouldThrowTimeoutException() | ||
{ | ||
await _sessionManager.RetrieveSession(TimeSpan.FromHours(1)); | ||
|
||
[TestMethod] | ||
public async Task SendSession_WithValidCancellationToken_ShouldNotThrowException() | ||
{ | ||
await _sessionManager.RetrieveSession(TimeSpan.FromHours(1)); | ||
var timeout = TimeSpan.Zero; | ||
await Assert.ThrowsExceptionAsync<TimeoutException>(() => _sessionManager.SendSession(timeout)); | ||
} | ||
|
||
var cts = new CancellationTokenSource(); | ||
await _sessionManager.SendSession(cts.Token); | ||
Assert.IsTrue(true); | ||
} | ||
[TestMethod] | ||
public async Task SendSession_WithValidCancellationToken_ShouldNotThrowException() | ||
{ | ||
await _sessionManager.RetrieveSession(TimeSpan.FromHours(1)); | ||
|
||
[TestMethod] | ||
public async Task SendSession_WithCancelledCancellationToken_ShouldThrowTaskCanceledException() | ||
{ | ||
await _sessionManager.RetrieveSession(TimeSpan.FromHours(1)); | ||
var cts = new CancellationTokenSource(); | ||
await _sessionManager.SendSession(cts.Token); | ||
Assert.IsTrue(true); | ||
} | ||
|
||
var cts = new CancellationTokenSource(); | ||
cts.Cancel(); | ||
await Assert.ThrowsExceptionAsync<TaskCanceledException>(() => _sessionManager.SendSession(cts.Token)); | ||
} | ||
[TestMethod] | ||
public async Task SendSession_WithCancelledCancellationToken_ShouldThrowTaskCanceledException() | ||
{ | ||
await _sessionManager.RetrieveSession(TimeSpan.FromHours(1)); | ||
|
||
var cts = new CancellationTokenSource(); | ||
cts.Cancel(); | ||
await Assert.ThrowsExceptionAsync<TaskCanceledException>(() => _sessionManager.SendSession(cts.Token)); | ||
} | ||
|
||
[TestMethod] | ||
public async Task RetrieveCachedSessionSession() | ||
{ | ||
await _sessionManager.RetrieveSession(TimeSpan.FromHours(1)); | ||
|
||
var session = _sessionManager.GetCachedSession(); | ||
Assert.IsNotNull(session); | ||
} | ||
[TestMethod] | ||
public void RetrieveNullCachedSessionSession() | ||
{ | ||
var session = _sessionManager.GetCachedSession(); | ||
Assert.IsNull(session); | ||
} | ||
[TestMethod] | ||
public async Task RetrieveCachedSessionSession() | ||
{ | ||
await _sessionManager.RetrieveSession(TimeSpan.FromHours(1)); | ||
|
||
var session = _sessionManager.GetCachedSession(); | ||
Assert.IsNotNull(session); | ||
} | ||
[TestMethod] | ||
public void RetrieveNullCachedSessionSession() | ||
{ | ||
var session = _sessionManager.GetCachedSession(); | ||
Assert.IsNull(session); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,7 +13,6 @@ | |
using Csla.Core; | ||
using Csla.Reflection; | ||
using Csla.Rules; | ||
using Csla.Core; | ||
|
||
namespace Csla.Blazor | ||
{ | ||
|
Oops, something went wrong.