diff --git a/backend/.editorconfig b/backend/.editorconfig index 07d258271..04394bcaa 100644 --- a/backend/.editorconfig +++ b/backend/.editorconfig @@ -184,4 +184,18 @@ dotnet_diagnostic.SA1623.severity = none dotnet_diagnostic.SYSLIB1045.severity = none # xUnit1033: Test classes decorated with 'Xunit.IClassFixture' or 'Xunit.ICollectionFixture' should add a constructor argument of type TFixture -dotnet_diagnostic.xUnit1033.severity = none \ No newline at end of file +dotnet_diagnostic.xUnit1033.severity = none + +[*Tests*.cs] +# MA0040: Forward the CancellationToken parameter to methods that take one +dotnet_diagnostic.MA0040.severity = none + +# xUnit1051: Calls to methods which accept CancellationToken should use TestContext.Current.CancellationToken +dotnet_diagnostic.xUnit1051.severity = none + +# CA1816: Dispose methods should call SuppressFinalize +dotnet_diagnostic.CA1816.severity = none + +[*Fixture.cs] +# CA1816: Dispose methods should call SuppressFinalize +dotnet_diagnostic.CA1816.severity = none \ No newline at end of file diff --git a/backend/extensions/Squidex.Extensions/Actions/Kafka/KafkaProducer.cs b/backend/extensions/Squidex.Extensions/Actions/Kafka/KafkaProducer.cs index 53f285ffd..db06c90a9 100644 --- a/backend/extensions/Squidex.Extensions/Actions/Kafka/KafkaProducer.cs +++ b/backend/extensions/Squidex.Extensions/Actions/Kafka/KafkaProducer.cs @@ -96,7 +96,10 @@ public sealed class KafkaProducer break; } - log.Log(level, "Kafka log {name}: {message}.", message.Name, message.Message); + if (log.IsEnabled(level)) + { + log.Log(level, "Kafka log {name}: {message}.", message.Name, message.Message); + } } private static void LogError(ILogger log, Error error) @@ -279,4 +282,4 @@ public sealed class KafkaProducer return schema?.Tag == expected || (schema is UnionSchema union && union.Schemas.Any(x => x.Tag == expected)); } } -#endif \ No newline at end of file +#endif diff --git a/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Assets/MongoAssetEntity.cs b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Assets/MongoAssetEntity.cs index fa46014b0..666da91de 100644 --- a/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Assets/MongoAssetEntity.cs +++ b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Assets/MongoAssetEntity.cs @@ -21,9 +21,7 @@ public record MongoAssetEntity : Asset, IVersionedEntity public static void RegisterClassMap() { - AssetItemClassMap.Register(); - - BsonClassMap.TryRegisterClassMap(cm => + BsonClassMap.RegisterClassMap(cm => { cm.MapProperty(x => x.DocumentId) .SetElementName("_id") @@ -34,7 +32,7 @@ public record MongoAssetEntity : Asset, IVersionedEntity .SetIsRequired(true); }); - BsonClassMap.TryRegisterClassMap(cm => + BsonClassMap.RegisterClassMap(cm => { cm.MapProperty(x => x.FileName) .SetElementName("fn") diff --git a/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Assets/MongoAssetFolderEntity.cs b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Assets/MongoAssetFolderEntity.cs index d826ddf12..83a94bbdc 100644 --- a/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Assets/MongoAssetFolderEntity.cs +++ b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Assets/MongoAssetFolderEntity.cs @@ -21,7 +21,7 @@ public record MongoAssetFolderEntity : AssetFolder, IVersionedEntity public static void RegisterClassMap() { - BsonClassMap.TryRegisterClassMap(cm => + BsonClassMap.RegisterClassMap(cm => { cm.MapProperty(x => x.DocumentId) .SetElementName("_id") @@ -32,14 +32,12 @@ public record MongoAssetFolderEntity : AssetFolder, IVersionedEntity .SetIsRequired(true); }); - BsonClassMap.TryRegisterClassMap(cm => + BsonClassMap.RegisterClassMap(cm => { cm.MapProperty(x => x.FolderName) .SetElementName("fn") .SetIsRequired(true); }); - - AssetItemClassMap.Register(); } public static MongoAssetFolderEntity Create(SnapshotWriteJob job) diff --git a/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Assets/MongoAssetFolderRepository.cs b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Assets/MongoAssetFolderRepository.cs index 6d32b4a8e..15dab49ed 100644 --- a/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Assets/MongoAssetFolderRepository.cs +++ b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Assets/MongoAssetFolderRepository.cs @@ -15,11 +15,6 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets; public sealed partial class MongoAssetFolderRepository(IMongoDatabase database) : MongoRepositoryBase(database), IAssetFolderRepository { - static MongoAssetFolderRepository() - { - MongoAssetFolderEntity.RegisterClassMap(); - } - protected override string CollectionName() { return "States_AssetFolders2"; diff --git a/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Assets/AssetItemClassMap.cs b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Assets/MongoAssetItemClassMap.cs similarity index 79% rename from backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Assets/AssetItemClassMap.cs rename to backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Assets/MongoAssetItemClassMap.cs index a819347f9..ae70155d5 100644 --- a/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Assets/AssetItemClassMap.cs +++ b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Assets/MongoAssetItemClassMap.cs @@ -10,13 +10,11 @@ using Squidex.Domain.Apps.Core.Assets; namespace Squidex.Domain.Apps.Entities.Assets; -internal static class AssetItemClassMap +internal static class MongoAssetItemClassMap { - public static void Register() + public static void RegisterClassMap() { - AppEntityClassMap.Register(); - - BsonClassMap.TryRegisterClassMap(cm => + BsonClassMap.RegisterClassMap(cm => { cm.MapProperty(x => x.ParentId) .SetElementName("pi") diff --git a/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Assets/MongoAssetRepository.cs b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Assets/MongoAssetRepository.cs index 6f6a7ed24..5122facb9 100644 --- a/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Assets/MongoAssetRepository.cs +++ b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Assets/MongoAssetRepository.cs @@ -24,11 +24,6 @@ public sealed partial class MongoAssetRepository : MongoRepositoryBase log, string shardKey) : base(database) { diff --git a/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Contents/MongoContentEntity.cs b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Contents/MongoContentEntity.cs index 1ec136b0e..bcb8a5787 100644 --- a/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Contents/MongoContentEntity.cs +++ b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Contents/MongoContentEntity.cs @@ -34,9 +34,7 @@ public record MongoContentEntity : Content, IVersionedEntity public static void RegisterClassMap() { - AppEntityClassMap.Register(); - - BsonClassMap.TryRegisterClassMap(cm => + BsonClassMap.RegisterClassMap(cm => { cm.MapProperty(x => x.DocumentId) .SetElementName("_id") @@ -71,7 +69,7 @@ public record MongoContentEntity : Content, IVersionedEntity .SetIgnoreIfDefault(true); }); - BsonClassMap.TryRegisterClassMap(cm => + BsonClassMap.RegisterClassMap(cm => { cm.MapProperty(x => x.SchemaId) .SetElementName("si") @@ -93,8 +91,6 @@ public record MongoContentEntity : Content, IVersionedEntity .SetElementName("sj") .SetIgnoreIfDefault(true); }); - - EntityClassMap.Register(); } public WriteContent ToState() diff --git a/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Contents/MongoContentRepository.cs b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Contents/MongoContentRepository.cs index 954dec61c..1b3166ab1 100644 --- a/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Contents/MongoContentRepository.cs +++ b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Contents/MongoContentRepository.cs @@ -49,15 +49,6 @@ public partial class MongoContentRepository( public bool CanUseTransactions { get; private set; } - static MongoContentRepository() - { - BsonEscapedDictionarySerializer.Register(); - BsonEscapedDictionarySerializer.Register(); - BsonEscapedDictionarySerializer.Register(); - BsonStringSerializer.Register(); - MongoContentEntity.RegisterClassMap(); - } - public async Task InitializeAsync( CancellationToken ct) { diff --git a/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Contents/Text/MongoTextIndexerState.cs b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Contents/Text/MongoTextIndexerState.cs index c53b7f29b..e3c168ae3 100644 --- a/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Contents/Text/MongoTextIndexerState.cs +++ b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Contents/Text/MongoTextIndexerState.cs @@ -5,13 +5,11 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using MongoDB.Bson.Serialization; using MongoDB.Driver; using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Entities.Contents.Repositories; using Squidex.Domain.Apps.Entities.Contents.Text.State; -using Squidex.Domain.Apps.Entities.MongoDb; using Squidex.Infrastructure; namespace Squidex.Domain.Apps.Entities.Contents.Text; @@ -21,19 +19,6 @@ public sealed class MongoTextIndexerState( IContentRepository contentRepository) : MongoRepositoryBase(database), ITextIndexerState, IDeleter { - static MongoTextIndexerState() - { - BsonUniqueContentIdSerializer.Register(); - - BsonClassMap.TryRegisterClassMap(cm => - { - cm.MapIdProperty(x => x.UniqueContentId); - - cm.MapProperty(x => x.State) - .SetElementName("s"); - }); - } - int IDeleter.Order => -2000; protected override string CollectionName() diff --git a/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Contents/Text/MongoTextStateClassMap.cs b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Contents/Text/MongoTextStateClassMap.cs new file mode 100644 index 000000000..0c60a4168 --- /dev/null +++ b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Contents/Text/MongoTextStateClassMap.cs @@ -0,0 +1,25 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using MongoDB.Bson.Serialization; +using Squidex.Domain.Apps.Entities.Contents.Text.State; + +namespace Squidex.Domain.Apps.Entities.Contents.Text; + +internal static class MongoTextStateClassMap +{ + public static void RegisterClassMap() + { + BsonClassMap.RegisterClassMap(cm => + { + cm.MapIdProperty(x => x.UniqueContentId); + + cm.MapProperty(x => x.State) + .SetElementName("s"); + }); + } +} diff --git a/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/History/MongoHistoryClassMap.cs b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/History/MongoHistoryClassMap.cs new file mode 100644 index 000000000..51502ace3 --- /dev/null +++ b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/History/MongoHistoryClassMap.cs @@ -0,0 +1,27 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using MongoDB.Bson.Serialization; + +namespace Squidex.Domain.Apps.Entities.History; + +internal static class MongoHistoryClassMap +{ + public static void RegisterClassMap() + { + BsonClassMap.RegisterClassMap(cm => + { + cm.AutoMap(); + + cm.MapProperty(x => x.OwnerId) + .SetElementName("AppId"); + + cm.MapProperty(x => x.EventType) + .SetElementName("Message"); + }); + } +} diff --git a/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/History/MongoHistoryEventRepository.cs b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/History/MongoHistoryEventRepository.cs index 68dd4f8eb..ed1a16d53 100644 --- a/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/History/MongoHistoryEventRepository.cs +++ b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/History/MongoHistoryEventRepository.cs @@ -17,16 +17,6 @@ public sealed class MongoHistoryEventRepository(IMongoDatabase database) : Mongo { static MongoHistoryEventRepository() { - BsonClassMap.TryRegisterClassMap(cm => - { - cm.AutoMap(); - - cm.MapProperty(x => x.OwnerId) - .SetElementName("AppId"); - - cm.MapProperty(x => x.EventType) - .SetElementName("Message"); - }); } protected override string CollectionName() diff --git a/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/AppEntityClassMap.cs b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/MongoAppEntityClassMap.cs similarity index 82% rename from backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/AppEntityClassMap.cs rename to backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/MongoAppEntityClassMap.cs index 63a6ee793..3f04c0f7b 100644 --- a/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/AppEntityClassMap.cs +++ b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/MongoAppEntityClassMap.cs @@ -10,13 +10,11 @@ using Squidex.Domain.Apps.Core; namespace Squidex.Domain.Apps.Entities; -public static class AppEntityClassMap +public static class MongoAppEntityClassMap { - public static void Register() + public static void RegisterClassMap() { - EntityClassMap.Register(); - - BsonClassMap.TryRegisterClassMap(cm => + BsonClassMap.RegisterClassMap(cm => { cm.MapProperty(x => x.AppId) .SetElementName("ai") diff --git a/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/EntityClassMap.cs b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/MongoEntityClassMap.cs similarity index 90% rename from backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/EntityClassMap.cs rename to backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/MongoEntityClassMap.cs index 40fd379aa..dc19a66a5 100644 --- a/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/EntityClassMap.cs +++ b/backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/MongoEntityClassMap.cs @@ -10,11 +10,11 @@ using Squidex.Infrastructure.Commands; namespace Squidex.Domain.Apps.Entities; -internal static class EntityClassMap +internal static class MongoEntityClassMap { - public static void Register() + public static void RegisterClassMap() { - BsonClassMap.TryRegisterClassMap(cm => + BsonClassMap.RegisterClassMap(cm => { cm.MapProperty(x => x.Id) .SetElementName("id") diff --git a/backend/src/Squidex.Data.MongoDb/Domain/Users/IdentityUserForwardingSerializer.cs b/backend/src/Squidex.Data.MongoDb/Domain/Users/IdentityUserForwardingSerializer.cs new file mode 100644 index 000000000..3a8a12484 --- /dev/null +++ b/backend/src/Squidex.Data.MongoDb/Domain/Users/IdentityUserForwardingSerializer.cs @@ -0,0 +1,37 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Microsoft.AspNetCore.Identity; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; + +namespace Squidex.Domain.Users; + +internal sealed class IdentityUserForwardingSerializer + : SerializerBase, IBsonDocumentSerializer +{ + private static readonly IBsonSerializer MongoUserSerializer = + BsonSerializer.LookupSerializer(); + + public override IdentityUser Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + { + args.NominalType = typeof(MongoUser); + return MongoUserSerializer.Deserialize(context, args); + } + + public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, IdentityUser value) + { + args.NominalType = typeof(MongoUser); + MongoUserSerializer.Serialize(context, args, (MongoUser)value); + } + + public bool TryGetMemberSerializationInfo(string memberName, out BsonSerializationInfo serializationInfo) + { + return ((IBsonDocumentSerializer)MongoUserSerializer) + .TryGetMemberSerializationInfo(memberName, out serializationInfo); + } +} diff --git a/backend/src/Squidex.Data.MongoDb/Domain/Users/MongoIdentityClassMap.cs b/backend/src/Squidex.Data.MongoDb/Domain/Users/MongoIdentityClassMap.cs new file mode 100644 index 000000000..951aa67c6 --- /dev/null +++ b/backend/src/Squidex.Data.MongoDb/Domain/Users/MongoIdentityClassMap.cs @@ -0,0 +1,116 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Security.Claims; +using Microsoft.AspNetCore.Identity; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; + +namespace Squidex.Domain.Users; + +internal static class MongoIdentityClassMap +{ + public static void RegisterClassMap() + { + BsonClassMap.RegisterClassMap>(cm => + { + cm.AutoMap(); + + cm.MapMember(x => x.Id) + .SetSerializer(new StringSerializer(BsonType.ObjectId)); + + cm.UnmapMember(x => x.ConcurrencyStamp); + }); + + BsonClassMap.RegisterClassMap(cm => + { + cm.MapConstructor(typeof(Claim).GetConstructors() + .First(x => + { + var parameters = x.GetParameters(); + + return parameters.Length == 2 && + parameters[0].Name == "type" && + parameters[0].ParameterType == typeof(string) && + parameters[1].Name == "value" && + parameters[1].ParameterType == typeof(string); + })) + .SetArguments( + [ + nameof(Claim.Type), + nameof(Claim.Value), + ]); + + cm.MapMember(x => x.Type); + cm.MapMember(x => x.Value); + }); + + BsonClassMap.RegisterClassMap(cm => + { + cm.MapConstructor(typeof(UserLogin).GetConstructors() + .First(x => + { + var parameters = x.GetParameters(); + + return parameters.Length == 3; + })) + .SetArguments( + [ + nameof(UserLogin.LoginProvider), + nameof(UserLogin.ProviderKey), + nameof(UserLogin.ProviderDisplayName), + ]); + + cm.AutoMap(); + }); + + BsonClassMap.RegisterClassMap>(cm => + { + cm.AutoMap(); + + cm.UnmapMember(x => x.UserId); + }); + + BsonClassMap.RegisterClassMap>(cm => + { + cm.AutoMap(); + + cm.MapMember(x => x.Id) + .SetSerializer(new StringSerializer(BsonType.ObjectId)); + + cm.MapMember(x => x.AccessFailedCount) + .SetIgnoreIfDefault(true); + + cm.MapMember(x => x.EmailConfirmed) + .SetIgnoreIfDefault(true); + + cm.MapMember(x => x.LockoutEnd) + .SetElementName("LockoutEndDateUtc").SetIgnoreIfNull(true); + + cm.MapMember(x => x.LockoutEnabled) + .SetIgnoreIfDefault(true); + + cm.MapMember(x => x.PasswordHash) + .SetIgnoreIfNull(true); + + cm.MapMember(x => x.PhoneNumber) + .SetIgnoreIfNull(true); + + cm.MapMember(x => x.PhoneNumberConfirmed) + .SetIgnoreIfDefault(true); + + cm.MapMember(x => x.SecurityStamp) + .SetIgnoreIfNull(true); + + cm.MapMember(x => x.TwoFactorEnabled) + .SetIgnoreIfDefault(true); + }); + + BsonSerializer.RegisterSerializer(new IdentityUserForwardingSerializer()); + } +} diff --git a/backend/src/Squidex.Data.MongoDb/Domain/Users/MongoRoleStore.cs b/backend/src/Squidex.Data.MongoDb/Domain/Users/MongoRoleStore.cs index 52292afff..e515b4d3c 100644 --- a/backend/src/Squidex.Data.MongoDb/Domain/Users/MongoRoleStore.cs +++ b/backend/src/Squidex.Data.MongoDb/Domain/Users/MongoRoleStore.cs @@ -6,9 +6,6 @@ // ========================================================================== using Microsoft.AspNetCore.Identity; -using MongoDB.Bson; -using MongoDB.Bson.Serialization; -using MongoDB.Bson.Serialization.Serializers; using MongoDB.Driver; using Squidex.Infrastructure; @@ -16,19 +13,6 @@ namespace Squidex.Domain.Users; public sealed class MongoRoleStore(IMongoDatabase database) : MongoRepositoryBase(database), IRoleStore { - static MongoRoleStore() - { - BsonClassMap.RegisterClassMap>(cm => - { - cm.AutoMap(); - - cm.MapMember(x => x.Id) - .SetSerializer(new StringSerializer(BsonType.ObjectId)); - - cm.UnmapMember(x => x.ConcurrencyStamp); - }); - } - protected override string CollectionName() { return "Identity_Roles"; diff --git a/backend/src/Squidex.Data.MongoDb/Domain/Users/MongoUserStore.cs b/backend/src/Squidex.Data.MongoDb/Domain/Users/MongoUserStore.cs index 6ea88e642..365ce0454 100644 --- a/backend/src/Squidex.Data.MongoDb/Domain/Users/MongoUserStore.cs +++ b/backend/src/Squidex.Data.MongoDb/Domain/Users/MongoUserStore.cs @@ -8,8 +8,6 @@ using System.Security.Claims; using Microsoft.AspNetCore.Identity; using MongoDB.Bson; -using MongoDB.Bson.Serialization; -using MongoDB.Bson.Serialization.Serializers; using MongoDB.Driver; using Squidex.Infrastructure; @@ -37,95 +35,6 @@ public sealed class MongoUserStore(IMongoDatabase database) : private const string RecoveryCodeTokenName = "RecoveryCodes"; private IMongoCollection queryableCollection; - static MongoUserStore() - { - BsonClassMap.RegisterClassMap(cm => - { - cm.MapConstructor(typeof(Claim).GetConstructors() - .First(x => - { - var parameters = x.GetParameters(); - - return parameters.Length == 2 && - parameters[0].Name == "type" && - parameters[0].ParameterType == typeof(string) && - parameters[1].Name == "value" && - parameters[1].ParameterType == typeof(string); - })) - .SetArguments( - [ - nameof(Claim.Type), - nameof(Claim.Value), - ]); - - cm.MapMember(x => x.Type); - cm.MapMember(x => x.Value); - }); - - BsonClassMap.RegisterClassMap(cm => - { - cm.MapConstructor(typeof(UserLogin).GetConstructors() - .First(x => - { - var parameters = x.GetParameters(); - - return parameters.Length == 3; - })) - .SetArguments( - [ - nameof(UserLogin.LoginProvider), - nameof(UserLogin.ProviderKey), - nameof(UserLogin.ProviderDisplayName), - ]); - - cm.AutoMap(); - }); - - BsonClassMap.RegisterClassMap>(cm => - { - cm.AutoMap(); - - cm.UnmapMember(x => x.UserId); - }); - - BsonClassMap.RegisterClassMap>(cm => - { - cm.AutoMap(); - - cm.MapMember(x => x.Id) - .SetSerializer(new StringSerializer(BsonType.ObjectId)); - - cm.MapMember(x => x.AccessFailedCount) - .SetIgnoreIfDefault(true); - - cm.MapMember(x => x.EmailConfirmed) - .SetIgnoreIfDefault(true); - - cm.MapMember(x => x.LockoutEnd) - .SetElementName("LockoutEndDateUtc").SetIgnoreIfNull(true); - - cm.MapMember(x => x.LockoutEnabled) - .SetIgnoreIfDefault(true); - - cm.MapMember(x => x.PasswordHash) - .SetIgnoreIfNull(true); - - cm.MapMember(x => x.PhoneNumber) - .SetIgnoreIfNull(true); - - cm.MapMember(x => x.PhoneNumberConfirmed) - .SetIgnoreIfDefault(true); - - cm.MapMember(x => x.SecurityStamp) - .SetIgnoreIfNull(true); - - cm.MapMember(x => x.TwoFactorEnabled) - .SetIgnoreIfDefault(true); - }); - - BsonSerializer.TryRegisterSerializer(new IdentityUserForwardingSerializer()); - } - protected override string CollectionName() { return "Identity_Users"; @@ -672,29 +581,4 @@ public sealed class MongoUserStore(IMongoDatabase database) : filter.Eq(x => x.LoginProvider, loginProvider), filter.Eq(x => x.ProviderKey, providerKey)); } - - private sealed class IdentityUserForwardingSerializer - : SerializerBase, IBsonDocumentSerializer - { - private static readonly IBsonSerializer MongoUserSerializer = - BsonSerializer.LookupSerializer(); - - public override IdentityUser Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) - { - args.NominalType = typeof(MongoUser); - return MongoUserSerializer.Deserialize(context, args); - } - - public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, IdentityUser value) - { - args.NominalType = typeof(MongoUser); - MongoUserSerializer.Serialize(context, args, (MongoUser)value); - } - - public bool TryGetMemberSerializationInfo(string memberName, out BsonSerializationInfo serializationInfo) - { - return ((IBsonDocumentSerializer)MongoUserSerializer) - .TryGetMemberSerializationInfo(memberName, out serializationInfo); - } - } } diff --git a/backend/src/Squidex.Data.MongoDb/Infrastructure/MongoClientFactory.cs b/backend/src/Squidex.Data.MongoDb/Infrastructure/MongoClientFactory.cs deleted file mode 100644 index 24e7e5c4f..000000000 --- a/backend/src/Squidex.Data.MongoDb/Infrastructure/MongoClientFactory.cs +++ /dev/null @@ -1,31 +0,0 @@ -// ========================================================================== -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex UG (haftungsbeschraenkt) -// All rights reserved. Licensed under the MIT license. -// ========================================================================== - -using MongoDB.Driver; -using Squidex.Infrastructure.Json.Objects; - -namespace Squidex.Infrastructure; - -public static class MongoClientFactory -{ - public static MongoClient Create(string? connectionString, Action? configure = null) - { - BsonDefaultConventions.Register(); - BsonDomainIdSerializer.Register(); - BsonEscapedDictionarySerializer.Register(); - BsonInstantSerializer.Register(); - BsonJsonValueSerializer.Register(); - BsonStringSerializer.Register(); - - var clientSettings = MongoClientSettings.FromConnectionString(connectionString); - - // If we really need custom config. - configure?.Invoke(clientSettings); - - return new MongoClient(clientSettings); - } -} diff --git a/backend/src/Squidex.Data.MongoDb/Infrastructure/MongoRepositoryBase.cs b/backend/src/Squidex.Data.MongoDb/Infrastructure/MongoRepositoryBase.cs index ea66d8f8b..e4787b775 100644 --- a/backend/src/Squidex.Data.MongoDb/Infrastructure/MongoRepositoryBase.cs +++ b/backend/src/Squidex.Data.MongoDb/Infrastructure/MongoRepositoryBase.cs @@ -87,6 +87,7 @@ public abstract class MongoRepositoryBase : MongoBase, IInitializable { try { + Console.WriteLine("AASDASD"); CreateCollection(); await SetupCollectionAsync(Collection, ct); diff --git a/backend/src/Squidex.Data.MongoDb/MongoClientFactory.cs b/backend/src/Squidex.Data.MongoDb/MongoClientFactory.cs new file mode 100644 index 000000000..32089269d --- /dev/null +++ b/backend/src/Squidex.Data.MongoDb/MongoClientFactory.cs @@ -0,0 +1,59 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Text.Json; +using MongoDB.Bson; +using MongoDB.Driver; +using Squidex.Domain.Apps.Entities; +using Squidex.Domain.Apps.Entities.Assets; +using Squidex.Domain.Apps.Entities.Contents; +using Squidex.Domain.Apps.Entities.Contents.Text; +using Squidex.Domain.Apps.Entities.History; +using Squidex.Domain.Apps.Entities.MongoDb; +using Squidex.Domain.Users; +using Squidex.Infrastructure; +using Squidex.Infrastructure.Json.Objects; + +namespace Squidex; + +public static class MongoClientFactory +{ + public static void SetupSerializer(JsonSerializerOptions jsonSerializerOptions, BsonType representation) + { + // Register the serializers first. + BsonDomainIdSerializer.Register(); + BsonEscapedDictionarySerializer.Register(); + BsonInstantSerializer.Register(); + BsonJsonValueSerializer.Register(); + BsonStringSerializer.Register(); + BsonUniqueContentIdSerializer.Register(); + BsonJsonConvention.Register(jsonSerializerOptions, representation); + + // Keep the order, because we have an inheritance between entities. + MongoEntityClassMap.RegisterClassMap(); + MongoAppEntityClassMap.RegisterClassMap(); + MongoAssetItemClassMap.RegisterClassMap(); + MongoAssetEntity.RegisterClassMap(); + MongoAssetFolderEntity.RegisterClassMap(); + MongoContentEntity.RegisterClassMap(); + MongoHistoryClassMap.RegisterClassMap(); + MongoIdentityClassMap.RegisterClassMap(); + MongoTextStateClassMap.RegisterClassMap(); + + BsonDefaultConventions.Register(); + } + + public static MongoClient Create(string? connectionString, Action? configure = null) + { + var clientSettings = MongoClientSettings.FromConnectionString(connectionString); + + // If we really need custom config. + configure?.Invoke(clientSettings); + + return new MongoClient(clientSettings); + } +} diff --git a/backend/src/Squidex.Data.MongoDb/ServiceExtensions.cs b/backend/src/Squidex.Data.MongoDb/ServiceExtensions.cs index 95a97eebf..335c436ec 100644 --- a/backend/src/Squidex.Data.MongoDb/ServiceExtensions.cs +++ b/backend/src/Squidex.Data.MongoDb/ServiceExtensions.cs @@ -70,7 +70,8 @@ public static class ServiceExtensions services.AddSingletonAs(c => { var options = c.GetRequiredService>(); - var mongoClient = GetMongoClient(config, "eventStore:mongoDb"); + + var mongoClient = GetMongoClient(config, c.GetRequiredService(), "eventStore:mongoDb"); var mongoDatabase = mongoClient.GetDatabase(mongoDatabaseName); return new MongoEventStore(mongoDatabase, options); @@ -85,7 +86,7 @@ public static class ServiceExtensions services.AddMongoAssetStore(c => { - var mongoClient = GetMongoClient(config, "assetStore:mongoDb"); + var mongoClient = GetMongoClient(config, c.GetRequiredService(), "assetStore:mongoDb"); var mongoDatabase = mongoClient.GetDatabase(mongoDatabaseName); return new GridFSBucket(mongoDatabase, new GridFSBucketOptions @@ -105,7 +106,7 @@ public static class ServiceExtensions return GetDatabase(c, mongoDatabaseName); }); - services.AddSingletonAs(c => GetMongoClient(config, "store:mongoDb")) + services.AddSingletonAs(c => GetMongoClient(config, c.GetRequiredService(), "store:mongoDb")) .As(); services.AddSingletonAs(c => GetDatabase(c, mongoDatabaseName)) @@ -288,14 +289,19 @@ public static class ServiceExtensions .As(); } - private static IMongoClient GetMongoClient(IConfiguration config, string prefix) + private static IMongoClient GetMongoClient(IConfiguration config, JsonSerializerOptions serializerOptions, string prefix) { + var representation = config.GetValue("store:mongoDB:valueRepresentation"); + var mongoConfiguration = config.GetRequiredValue($"{prefix}:configuration")!; var mongoCertificate = config.GetValue($"{prefix}:certificate"); + var cacheKey = $"{mongoConfiguration}_{mongoCertificate}"; return Singletons.GetOrAdd(cacheKey, _ => { + MongoClientFactory.SetupSerializer(serializerOptions, representation); + return MongoClientFactory.Create(mongoConfiguration, settings => { if (!string.IsNullOrWhiteSpace(mongoCertificate)) diff --git a/backend/tests/Squidex.Data.Tests/EntityFramework/Migrations/MySqlMigrationTests.cs b/backend/tests/Squidex.Data.Tests/EntityFramework/Migrations/MySqlMigrationTests.cs index 1c4bd93e0..722021ea8 100644 --- a/backend/tests/Squidex.Data.Tests/EntityFramework/Migrations/MySqlMigrationTests.cs +++ b/backend/tests/Squidex.Data.Tests/EntityFramework/Migrations/MySqlMigrationTests.cs @@ -20,12 +20,12 @@ public class MySqlMigrationTests : IAsyncLifetime { private readonly MySqlContainer mysql = new MySqlBuilder("mysql:8.0").Build(); - public async Task InitializeAsync() + public async ValueTask InitializeAsync() { - await mysql.StartAsync(); + await mysql.StartAsync(TestContext.Current.CancellationToken); } - public async Task DisposeAsync() + public async ValueTask DisposeAsync() { await mysql.DisposeAsync(); } diff --git a/backend/tests/Squidex.Data.Tests/EntityFramework/Migrations/PostgresMigrationTests.cs b/backend/tests/Squidex.Data.Tests/EntityFramework/Migrations/PostgresMigrationTests.cs index 29574329c..d7dd7a589 100644 --- a/backend/tests/Squidex.Data.Tests/EntityFramework/Migrations/PostgresMigrationTests.cs +++ b/backend/tests/Squidex.Data.Tests/EntityFramework/Migrations/PostgresMigrationTests.cs @@ -22,12 +22,12 @@ public class PostgresMigrationTests : IAsyncLifetime new PostgreSqlBuilder("postgis/postgis") .Build(); - public async Task InitializeAsync() + public async ValueTask InitializeAsync() { - await postgreSql.StartAsync(); + await postgreSql.StartAsync(TestContext.Current.CancellationToken); } - public async Task DisposeAsync() + public async ValueTask DisposeAsync() { await postgreSql.DisposeAsync(); } diff --git a/backend/tests/Squidex.Data.Tests/EntityFramework/Migrations/SqlServerMigrationTests.cs b/backend/tests/Squidex.Data.Tests/EntityFramework/Migrations/SqlServerMigrationTests.cs index 9dd05cc8e..38808e059 100644 --- a/backend/tests/Squidex.Data.Tests/EntityFramework/Migrations/SqlServerMigrationTests.cs +++ b/backend/tests/Squidex.Data.Tests/EntityFramework/Migrations/SqlServerMigrationTests.cs @@ -22,12 +22,12 @@ public class SqlServerMigrationTests : IAsyncLifetime new MsSqlBuilder("mcr.microsoft.com/mssql/server:2022-CU14-ubuntu-22.04") .Build(); - public async Task InitializeAsync() + public async ValueTask InitializeAsync() { - await sqlServer.StartAsync(); + await sqlServer.StartAsync(TestContext.Current.CancellationToken); } - public async Task DisposeAsync() + public async ValueTask DisposeAsync() { await sqlServer.DisposeAsync(); } diff --git a/backend/tests/Squidex.Data.Tests/EntityFramework/TestHelpers/MySqlFixture.cs b/backend/tests/Squidex.Data.Tests/EntityFramework/TestHelpers/MySqlFixture.cs index ebcd50e09..b497a6003 100644 --- a/backend/tests/Squidex.Data.Tests/EntityFramework/TestHelpers/MySqlFixture.cs +++ b/backend/tests/Squidex.Data.Tests/EntityFramework/TestHelpers/MySqlFixture.cs @@ -37,9 +37,9 @@ public class MySqlFixture(string? reuseId = null) : IAsyncLifetime, ISqlContentF public IDbContextNamedFactory DbContextNamedFactory => services.GetRequiredService>(); - public async Task InitializeAsync() + public async ValueTask InitializeAsync() { - await mysql.StartAsync(); + await mysql.StartAsync(TestContext.Current.CancellationToken); var connectionString = $"{mysql.GetConnectionString()};AllowLoadLocalInfile=true;MaxPoolSize=1000"; @@ -77,13 +77,13 @@ public class MySqlFixture(string? reuseId = null) : IAsyncLifetime, ISqlContentF } } - public async Task DisposeAsync() + public async ValueTask DisposeAsync() { foreach (var service in services.GetRequiredService>()) { await service.ReleaseAsync(default); } - await mysql.StopAsync(); + await mysql.StopAsync(TestContext.Current.CancellationToken); } } diff --git a/backend/tests/Squidex.Data.Tests/EntityFramework/TestHelpers/PostgresFixture.cs b/backend/tests/Squidex.Data.Tests/EntityFramework/TestHelpers/PostgresFixture.cs index 5143b53b3..4f613fd46 100644 --- a/backend/tests/Squidex.Data.Tests/EntityFramework/TestHelpers/PostgresFixture.cs +++ b/backend/tests/Squidex.Data.Tests/EntityFramework/TestHelpers/PostgresFixture.cs @@ -36,9 +36,9 @@ public class PostgresFixture(string? reuseId) : IAsyncLifetime, ISqlContentFixtu public IDbContextNamedFactory DbContextNamedFactory => services.GetRequiredService>(); - public async Task InitializeAsync() + public async ValueTask InitializeAsync() { - await postgreSql.StartAsync(); + await postgreSql.StartAsync(TestContext.Current.CancellationToken); var connectionString = postgreSql.GetConnectionString(); @@ -72,13 +72,13 @@ public class PostgresFixture(string? reuseId) : IAsyncLifetime, ISqlContentFixtu } } - public async Task DisposeAsync() + public async ValueTask DisposeAsync() { foreach (var service in services.GetRequiredService>()) { await service.ReleaseAsync(default); } - await postgreSql.StopAsync(); + await postgreSql.StopAsync(TestContext.Current.CancellationToken); } } diff --git a/backend/tests/Squidex.Data.Tests/EntityFramework/TestHelpers/SqlServerFixture.cs b/backend/tests/Squidex.Data.Tests/EntityFramework/TestHelpers/SqlServerFixture.cs index bcda4438d..26a5608f9 100644 --- a/backend/tests/Squidex.Data.Tests/EntityFramework/TestHelpers/SqlServerFixture.cs +++ b/backend/tests/Squidex.Data.Tests/EntityFramework/TestHelpers/SqlServerFixture.cs @@ -37,10 +37,10 @@ public class SqlServerFixture(string? reuseId = null) : IAsyncLifetime, ISqlCont public IDbContextNamedFactory DbContextNamedFactory => services.GetRequiredService>(); - public async Task InitializeAsync() + public async ValueTask InitializeAsync() { - await sqlServer.StartAsync(); - await sqlServer.ExecScriptAsync($"create database squidex;"); + await sqlServer.StartAsync(TestContext.Current.CancellationToken); + await sqlServer.ExecScriptAsync($"create database squidex;", TestContext.Current.CancellationToken); var connectionString = GetConnectionString(); @@ -74,14 +74,14 @@ public class SqlServerFixture(string? reuseId = null) : IAsyncLifetime, ISqlCont } } - public async Task DisposeAsync() + public async ValueTask DisposeAsync() { foreach (var service in services.GetRequiredService>()) { await service.ReleaseAsync(default); } - await sqlServer.StopAsync(); + await sqlServer.StopAsync(TestContext.Current.CancellationToken); } private string GetConnectionString() diff --git a/backend/tests/Squidex.Data.Tests/EntityFramework/TestHelpers/TestEntity.cs b/backend/tests/Squidex.Data.Tests/EntityFramework/TestHelpers/TestEntity.cs index 6e96820ad..6b0b499e6 100644 --- a/backend/tests/Squidex.Data.Tests/EntityFramework/TestHelpers/TestEntity.cs +++ b/backend/tests/Squidex.Data.Tests/EntityFramework/TestHelpers/TestEntity.cs @@ -6,7 +6,6 @@ // ========================================================================== using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; using NetTopologySuite.Geometries; #pragma warning disable MA0048 // File name must match type name diff --git a/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Assets/AssetQueryTests.cs b/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Assets/AssetQueryTests.cs index 3f5aa8f37..b5d63248c 100644 --- a/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Assets/AssetQueryTests.cs +++ b/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Assets/AssetQueryTests.cs @@ -24,12 +24,6 @@ public class AssetQueryTests { private readonly DomainId appId = DomainId.NewGuid(); - static AssetQueryTests() - { - MongoAssetEntity.RegisterClassMap(); - MongoTestUtils.SetupBson(); - } - [Fact] public void Should_throw_exception_for_full_text_search() { diff --git a/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/AdaptionTests.cs b/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/AdaptionTests.cs index eee06fb19..6e0c2d852 100644 --- a/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/AdaptionTests.cs +++ b/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/AdaptionTests.cs @@ -5,18 +5,13 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using Squidex.Domain.Apps.Entities.Contents; using Squidex.Domain.Apps.Entities.Contents.Operations; +using Squidex.MongoDb.TestHelpers; namespace Squidex.MongoDb.Domain.Contents; public class AdaptionTests { - static AdaptionTests() - { - MongoContentEntity.RegisterClassMap(); - } - [Fact] public void Should_adapt_to_meta_field() { diff --git a/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/ContentMappingTests.cs b/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/ContentMappingTests.cs index 3911e6281..0d6288a3a 100644 --- a/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/ContentMappingTests.cs +++ b/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/ContentMappingTests.cs @@ -9,6 +9,7 @@ using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Entities.Contents; using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Infrastructure.States; +using Squidex.MongoDb.TestHelpers; namespace Squidex.MongoDb.Domain.Contents; diff --git a/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/ContentQueryTests.cs b/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/ContentQueryTests.cs index 98bb1fa05..ce6383aeb 100644 --- a/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/ContentQueryTests.cs +++ b/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/ContentQueryTests.cs @@ -24,13 +24,6 @@ namespace Squidex.MongoDb.Domain.Contents; public class ContentQueryTests : GivenContext { - static ContentQueryTests() - { - MongoContentEntity.RegisterClassMap(); - - MongoTestUtils.SetupBson(); - } - public ContentQueryTests() { Schema = Schema with { Version = 3 }; diff --git a/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/ExtensionsTests.cs b/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/ExtensionsTests.cs index 18cc8be2b..6194e6328 100644 --- a/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/ExtensionsTests.cs +++ b/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/ExtensionsTests.cs @@ -8,17 +8,13 @@ using MongoDB.Bson.Serialization; using MongoDB.Driver; using Squidex.Domain.Apps.Entities.Contents; +using Squidex.MongoDb.TestHelpers; using ExtensionSut = Squidex.Domain.Apps.Entities.Contents.Operations.Extensions; namespace Squidex.MongoDb.Domain.Contents; public class ExtensionsTests { - public ExtensionsTests() - { - MongoContentEntity.RegisterClassMap(); - } - [Fact] public void Should_build_projection_without_fields() { diff --git a/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/IndexParserTests.cs b/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/IndexParserTests.cs index 2cd5c09e6..44f65b714 100644 --- a/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/IndexParserTests.cs +++ b/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/IndexParserTests.cs @@ -9,6 +9,7 @@ using MongoDB.Bson; using Squidex.Domain.Apps.Entities.Contents; using Squidex.Infrastructure.Queries; using Squidex.Infrastructure.States; +using Squidex.MongoDb.TestHelpers; namespace Squidex.MongoDb.Domain.Contents; @@ -26,11 +27,6 @@ public class IndexParserTests }, }; - static IndexParserTests() - { - MongoContentEntity.RegisterClassMap(); - } - [Fact] public void Should_parse_index() { diff --git a/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/Text/AtlasTextIndexFixture.cs b/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/Text/AtlasTextIndexFixture.cs index d208a8902..b9981e0e8 100644 --- a/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/Text/AtlasTextIndexFixture.cs +++ b/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/Text/AtlasTextIndexFixture.cs @@ -11,7 +11,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Squidex.Domain.Apps.Entities.Contents.Text; using Squidex.Domain.Apps.Entities.TestHelpers; -using Squidex.Infrastructure; using Squidex.MongoDb.TestHelpers; namespace Squidex.MongoDb.Domain.Contents.Text; @@ -22,8 +21,6 @@ public sealed class AtlasTextIndexFixture : IAsyncLifetime public AtlasTextIndexFixture() { - MongoTestUtils.SetupBson(); - var mongoClient = MongoClientFactory.Create(TestConfig.Configuration["atlas:configuration"]!); var mongoDatabase = mongoClient.GetDatabase(TestConfig.Configuration["atlas:database"]!); @@ -50,13 +47,13 @@ public sealed class AtlasTextIndexFixture : IAsyncLifetime Index = services.GetRequiredService(); } - public Task InitializeAsync() + public async ValueTask InitializeAsync() { - return Index.InitializeAsync(default); + await Index.InitializeAsync(default); } - public Task DisposeAsync() + public ValueTask DisposeAsync() { - return Task.CompletedTask; + return default; } } diff --git a/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/TokenizerTests.cs b/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/TokenizerTests.cs index d31ab590a..bc44e17dc 100644 --- a/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/TokenizerTests.cs +++ b/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Contents/TokenizerTests.cs @@ -6,6 +6,7 @@ // ========================================================================== using Squidex.Domain.Apps.Entities.Contents.Text; +using Squidex.MongoDb.TestHelpers; namespace Squidex.MongoDb.Domain.Contents; diff --git a/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Schemas/MongoSchemasHashTests.cs b/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Schemas/MongoSchemasHashTests.cs index 44b488cda..af6748d13 100644 --- a/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Schemas/MongoSchemasHashTests.cs +++ b/backend/tests/Squidex.Data.Tests/MongoDb/Domain/Schemas/MongoSchemasHashTests.cs @@ -24,14 +24,14 @@ public class MongoSchemasHashTests(MongoFixture fixture) : GivenContext, IAsyncL { private readonly MongoSchemasHash sut = new MongoSchemasHash(fixture.Database); - public async Task InitializeAsync() + public async ValueTask InitializeAsync() { await sut.InitializeAsync(default); } - public Task DisposeAsync() + public ValueTask DisposeAsync() { - return Task.CompletedTask; + return default; } [Fact] diff --git a/backend/tests/Squidex.Data.Tests/MongoDb/Infrastructure/EventConsumerProcessorIntegrationTests.cs b/backend/tests/Squidex.Data.Tests/MongoDb/Infrastructure/EventConsumerProcessorIntegrationTests.cs index b0dfbbf5e..d610f6847 100644 --- a/backend/tests/Squidex.Data.Tests/MongoDb/Infrastructure/EventConsumerProcessorIntegrationTests.cs +++ b/backend/tests/Squidex.Data.Tests/MongoDb/Infrastructure/EventConsumerProcessorIntegrationTests.cs @@ -14,6 +14,7 @@ using Squidex.Infrastructure.EventSourcing.Consume; using Squidex.Infrastructure.Reflection; using Squidex.Infrastructure.States; using Squidex.Infrastructure.TestHelpers; +using Squidex.MongoDb.TestHelpers; #pragma warning disable MA0040 // Forward the CancellationToken parameter to methods that take one diff --git a/backend/tests/Squidex.Data.Tests/MongoDb/Infrastructure/EventSourcing/MongoEventStoreFixture.cs b/backend/tests/Squidex.Data.Tests/MongoDb/Infrastructure/EventSourcing/MongoEventStoreFixture.cs index 30051733b..2ba5b236e 100644 --- a/backend/tests/Squidex.Data.Tests/MongoDb/Infrastructure/EventSourcing/MongoEventStoreFixture.cs +++ b/backend/tests/Squidex.Data.Tests/MongoDb/Infrastructure/EventSourcing/MongoEventStoreFixture.cs @@ -8,8 +8,8 @@ using Microsoft.Extensions.Options; using MongoDB.Driver; using Squidex.Events.Mongo; -using Squidex.Infrastructure; using Squidex.Infrastructure.TestHelpers; +using Squidex.MongoDb.TestHelpers; #pragma warning disable MA0048 // File name must match type name @@ -37,11 +37,6 @@ public abstract class MongoEventStoreFixture : IAsyncLifetime public IMongoDatabase Database { get; } - static MongoEventStoreFixture() - { - BsonJsonConvention.Register(TestUtils.DefaultOptions()); - } - protected MongoEventStoreFixture(string connectionString) { var mongoClient = MongoClientFactory.Create(connectionString); @@ -52,13 +47,13 @@ public abstract class MongoEventStoreFixture : IAsyncLifetime EventStore = new MongoEventStore(mongoDatabase, Options.Create(new MongoEventStoreOptions())); } - public Task InitializeAsync() + public async ValueTask InitializeAsync() { - return EventStore.InitializeAsync(default); + await EventStore.InitializeAsync(default); } - public Task DisposeAsync() + public ValueTask DisposeAsync() { - return Task.CompletedTask; + return default; } } diff --git a/backend/tests/Squidex.Data.Tests/MongoDb/Infrastructure/NamedIdTests.cs b/backend/tests/Squidex.Data.Tests/MongoDb/Infrastructure/NamedIdTests.cs index f0d444853..b0cd2caaa 100644 --- a/backend/tests/Squidex.Data.Tests/MongoDb/Infrastructure/NamedIdTests.cs +++ b/backend/tests/Squidex.Data.Tests/MongoDb/Infrastructure/NamedIdTests.cs @@ -12,11 +12,6 @@ namespace Squidex.MongoDb.Infrastructure; public class NamedIdTests { - static NamedIdTests() - { - MongoTestUtils.SetupBson(); - } - [Fact] public void Should_serialize_and_deserialize_null_guid_token() { diff --git a/backend/tests/Squidex.Data.Tests/MongoDb/Infrastructure/Queries/MongoQueryTests.cs b/backend/tests/Squidex.Data.Tests/MongoDb/Infrastructure/Queries/MongoQueryTests.cs index 5aa686cfc..f8fe477de 100644 --- a/backend/tests/Squidex.Data.Tests/MongoDb/Infrastructure/Queries/MongoQueryTests.cs +++ b/backend/tests/Squidex.Data.Tests/MongoDb/Infrastructure/Queries/MongoQueryTests.cs @@ -33,11 +33,6 @@ public class MongoQueryTests public long Version { get; set; } } - static MongoQueryTests() - { - MongoTestUtils.SetupBson(); - } - [Fact] public void Should_not_throw_exception_for_invalid_field() { diff --git a/backend/tests/Squidex.Data.Tests/MongoDb/TestHelpers/DocumentDbFixture.cs b/backend/tests/Squidex.Data.Tests/MongoDb/TestHelpers/DocumentDbFixture.cs index 13fb7fb71..83dd91bbb 100644 --- a/backend/tests/Squidex.Data.Tests/MongoDb/TestHelpers/DocumentDbFixture.cs +++ b/backend/tests/Squidex.Data.Tests/MongoDb/TestHelpers/DocumentDbFixture.cs @@ -28,8 +28,6 @@ public class DocumentDbFixture public DocumentDbFixture() { - MongoTestUtils.SetupBson(); - var settings = MongoClientSettings.FromConnectionString( TestConfig.Configuration.GetValue("documentDb:configuration") ); diff --git a/backend/tests/Squidex.Data.Tests/MongoDb/TestHelpers/MongoFixture.cs b/backend/tests/Squidex.Data.Tests/MongoDb/TestHelpers/MongoFixture.cs index d20eba25b..cff44cc96 100644 --- a/backend/tests/Squidex.Data.Tests/MongoDb/TestHelpers/MongoFixture.cs +++ b/backend/tests/Squidex.Data.Tests/MongoDb/TestHelpers/MongoFixture.cs @@ -30,20 +30,15 @@ public class MongoFixture : IAsyncLifetime public IMongoDatabase Database => Client.GetDatabase("Test"); - public MongoFixture() + public async ValueTask InitializeAsync() { - MongoTestUtils.SetupBson(); - } - - public async Task InitializeAsync() - { - await mongoDb.StartAsync(); + await mongoDb.StartAsync(TestContext.Current.CancellationToken); - Client = new MongoClient(mongoDb.GetConnectionString()); + Client = MongoClientFactory.Create(mongoDb.GetConnectionString()); } - public async Task DisposeAsync() + public async ValueTask DisposeAsync() { - await mongoDb.StopAsync(); + await mongoDb.StopAsync(TestContext.Current.CancellationToken); } } diff --git a/backend/tests/Squidex.Data.Tests/MongoDb/TestHelpers/MongoSerializerFixture.cs b/backend/tests/Squidex.Data.Tests/MongoDb/TestHelpers/MongoSerializerFixture.cs new file mode 100644 index 000000000..f1358ede3 --- /dev/null +++ b/backend/tests/Squidex.Data.Tests/MongoDb/TestHelpers/MongoSerializerFixture.cs @@ -0,0 +1,26 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using MongoDB.Bson; +using Squidex.Domain.Apps.Core.TestHelpers; +using Squidex.MongoDb.TestHelpers; + +[assembly: AssemblyFixture(typeof(MongoSerializerFixture))] + +namespace Squidex.MongoDb.TestHelpers; + +internal sealed class MongoSerializerFixture : IDisposable +{ + public MongoSerializerFixture() + { + MongoClientFactory.SetupSerializer(TestUtils.DefaultOptions(), BsonType.String); + } + + public void Dispose() + { + } +} diff --git a/backend/tests/Squidex.Data.Tests/MongoDb/TestHelpers/MongoTestUtils.cs b/backend/tests/Squidex.Data.Tests/MongoDb/TestHelpers/MongoTestUtils.cs index d96c309ec..9c2d0d509 100644 --- a/backend/tests/Squidex.Data.Tests/MongoDb/TestHelpers/MongoTestUtils.cs +++ b/backend/tests/Squidex.Data.Tests/MongoDb/TestHelpers/MongoTestUtils.cs @@ -9,10 +9,7 @@ using MongoDB.Bson; using MongoDB.Bson.IO; using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization.Attributes; -using MongoDB.Bson.Serialization.Serializers; using Squidex.Domain.Apps.Core.TestHelpers; -using Squidex.Infrastructure; -using Squidex.Infrastructure.Json.Objects; namespace Squidex.MongoDb.TestHelpers; @@ -27,22 +24,6 @@ public static class MongoTestUtils public T Value2 { get; set; } } - static MongoTestUtils() - { - SetupBson(); - } - - public static void SetupBson() - { - BsonDefaultConventions.Register(); - BsonDomainIdSerializer.Register(); - BsonEscapedDictionarySerializer.Register(); - BsonInstantSerializer.Register(); - BsonJsonConvention.Register(TestUtils.DefaultOptions()); - BsonJsonValueSerializer.Register(); - BsonStringSerializer.Register(); - } - public static T SerializeAndDeserializeBson(this T value) { return value.SerializeAndDeserializeBson(); diff --git a/backend/tests/Squidex.Data.Tests/Shared/AssetFolderRepositoryTests.cs b/backend/tests/Squidex.Data.Tests/Shared/AssetFolderRepositoryTests.cs index c9661569b..818d3a6ea 100644 --- a/backend/tests/Squidex.Data.Tests/Shared/AssetFolderRepositoryTests.cs +++ b/backend/tests/Squidex.Data.Tests/Shared/AssetFolderRepositoryTests.cs @@ -97,7 +97,7 @@ public abstract class AssetFolderRepositoryTests : GivenContext public static readonly TheoryData ParentIds = new TheoryData { - { null }, + { null as DomainId? }, { DomainId.Empty }, }; diff --git a/backend/tests/Squidex.Data.Tests/Shared/AssetRepositoryTests.cs b/backend/tests/Squidex.Data.Tests/Shared/AssetRepositoryTests.cs index 1320fb8d7..728aec7cd 100644 --- a/backend/tests/Squidex.Data.Tests/Shared/AssetRepositoryTests.cs +++ b/backend/tests/Squidex.Data.Tests/Shared/AssetRepositoryTests.cs @@ -123,7 +123,7 @@ public abstract class AssetRepositoryTests : GivenContext public static readonly TheoryData ParentIds = new TheoryData { - { null }, + { null as DomainId? }, { DomainId.Empty }, }; diff --git a/backend/tests/Squidex.Data.Tests/Squidex.Data.Tests.csproj b/backend/tests/Squidex.Data.Tests/Squidex.Data.Tests.csproj index 0b477497a..999222b74 100644 --- a/backend/tests/Squidex.Data.Tests/Squidex.Data.Tests.csproj +++ b/backend/tests/Squidex.Data.Tests/Squidex.Data.Tests.csproj @@ -41,7 +41,7 @@ - + all runtime; build; native; contentfiles; analyzers diff --git a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/ExpressionsAttribute.cs b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/ExpressionsAttribute.cs index 1f124fecc..39ca39bf0 100644 --- a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/ExpressionsAttribute.cs +++ b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/ExpressionsAttribute.cs @@ -7,37 +7,41 @@ using System.Reflection; using Xunit.Sdk; +using Xunit.v3; namespace Squidex.Domain.Apps.Core.Operations.HandleRules; public sealed class ExpressionsAttribute(string? interpolationOld, string? interpolationNew, string? script, string? liquid) : DataAttribute { - public override IEnumerable GetData(MethodInfo testMethod) + public override ValueTask> GetData(MethodInfo testMethod, DisposalTracker disposalTracker) { + var rows = new List(); + if (interpolationOld != null) { - yield return new object[] { interpolationOld }; + rows.Add(new TheoryDataRow(interpolationOld)); } if (interpolationNew != null) { - yield return new object[] { interpolationNew }; + rows.Add(new TheoryDataRow(interpolationNew)); } if (script != null) { - yield return new object[] - { - $"Script(`{script}`)", - }; + rows.Add(new TheoryDataRow($"Script(`{script}`)")); } if (liquid != null) { - yield return new object[] - { - $"Liquid({liquid})", - }; + rows.Add(new TheoryDataRow($"Liquid({liquid})")); } + + return new ValueTask>(rows); + } + + public override bool SupportsDiscoveryEnumeration() + { + return true; } } diff --git a/backend/tests/Squidex.Domain.Apps.Core.Tests/Squidex.Domain.Apps.Core.Tests.csproj b/backend/tests/Squidex.Domain.Apps.Core.Tests/Squidex.Domain.Apps.Core.Tests.csproj index bc84a2fe5..422edfaeb 100644 --- a/backend/tests/Squidex.Domain.Apps.Core.Tests/Squidex.Domain.Apps.Core.Tests.csproj +++ b/backend/tests/Squidex.Domain.Apps.Core.Tests/Squidex.Domain.Apps.Core.Tests.csproj @@ -30,7 +30,7 @@ - + all runtime; build; native; contentfiles; analyzers diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Billing/UsageNotifierWorkerTest.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Billing/UsageNotifierWorkerTests.cs similarity index 98% rename from backend/tests/Squidex.Domain.Apps.Entities.Tests/Billing/UsageNotifierWorkerTest.cs rename to backend/tests/Squidex.Domain.Apps.Entities.Tests/Billing/UsageNotifierWorkerTests.cs index c41628258..4b874e798 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Billing/UsageNotifierWorkerTest.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Billing/UsageNotifierWorkerTests.cs @@ -16,7 +16,7 @@ using Squidex.Shared.Users; namespace Squidex.Domain.Apps.Entities.Billing; -public class UsageNotifierWorkerTest : GivenContext +public class UsageNotifierWorkerTests : GivenContext { private readonly TestState state = new TestState("Default"); private readonly IClock clock = A.Fake(); @@ -25,7 +25,7 @@ public class UsageNotifierWorkerTest : GivenContext private readonly UsageNotifierWorker sut; private Instant time = SystemClock.Instance.GetCurrentInstant(); - public UsageNotifierWorkerTest() + public UsageNotifierWorkerTests() { A.CallTo(() => clock.GetCurrentInstant()) .ReturnsLazily(() => time); diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Text/AzureTextIndexFixture.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Text/AzureTextIndexFixture.cs index 1ef21d9cd..7b7f715dc 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Text/AzureTextIndexFixture.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Text/AzureTextIndexFixture.cs @@ -22,13 +22,13 @@ public sealed class AzureTextIndexFixture : IAsyncLifetime TestConfig.Configuration["azureText:indexName"]!); } - public Task InitializeAsync() + public async ValueTask InitializeAsync() { - return Index.InitializeAsync(default); + await Index.InitializeAsync(default); } - public Task DisposeAsync() + public ValueTask DisposeAsync() { - return Task.CompletedTask; + return default; } } diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Text/ElasticSearchTextIndexFixture.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Text/ElasticSearchTextIndexFixture.cs index de9070718..3e3b1a035 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Text/ElasticSearchTextIndexFixture.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Text/ElasticSearchTextIndexFixture.cs @@ -22,9 +22,9 @@ public sealed class ElasticSearchTextIndexFixture : IAsyncLifetime public ElasticSearchTextIndex Index { get; private set; } - public async Task InitializeAsync() + public async ValueTask InitializeAsync() { - await elastic.StopAsync(); + await elastic.StartAsync(TestContext.Current.CancellationToken); Index = new ElasticSearchTextIndex( new ElasticSearchClient(elastic.GetConnectionString()), @@ -34,8 +34,8 @@ public sealed class ElasticSearchTextIndexFixture : IAsyncLifetime await Index.InitializeAsync(default); } - public Task DisposeAsync() + public async ValueTask DisposeAsync() { - return Task.CompletedTask; + await elastic.StopAsync(TestContext.Current.CancellationToken); } } diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Text/OpenSearchTextIndexFixture.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Text/OpenSearchTextIndexFixture.cs index 8100d26fb..701e2eeae 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Text/OpenSearchTextIndexFixture.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Text/OpenSearchTextIndexFixture.cs @@ -23,13 +23,13 @@ public sealed class OpenSearchTextIndexFixture : IAsyncLifetime TestUtils.DefaultSerializer); } - public Task InitializeAsync() + public async ValueTask InitializeAsync() { - return Index.InitializeAsync(default); + await Index.InitializeAsync(default); } - public Task DisposeAsync() + public ValueTask DisposeAsync() { - return Task.CompletedTask; + return default; } } diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Squidex.Domain.Apps.Entities.Tests.csproj b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Squidex.Domain.Apps.Entities.Tests.csproj index 1d586f950..db9fc3f31 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Squidex.Domain.Apps.Entities.Tests.csproj +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Squidex.Domain.Apps.Entities.Tests.csproj @@ -43,8 +43,8 @@ - - + + all runtime; build; native; contentfiles; analyzers diff --git a/backend/tests/Squidex.Domain.Users.Tests/Squidex.Domain.Users.Tests.csproj b/backend/tests/Squidex.Domain.Users.Tests/Squidex.Domain.Users.Tests.csproj index 4dd112148..a7dd0eafa 100644 --- a/backend/tests/Squidex.Domain.Users.Tests/Squidex.Domain.Users.Tests.csproj +++ b/backend/tests/Squidex.Domain.Users.Tests/Squidex.Domain.Users.Tests.csproj @@ -26,7 +26,7 @@ - + all runtime; build; native; contentfiles; analyzers diff --git a/backend/tests/Squidex.Infrastructure.Tests/Squidex.Infrastructure.Tests.csproj b/backend/tests/Squidex.Infrastructure.Tests/Squidex.Infrastructure.Tests.csproj index afdb72ed3..f8bcdb2ff 100644 --- a/backend/tests/Squidex.Infrastructure.Tests/Squidex.Infrastructure.Tests.csproj +++ b/backend/tests/Squidex.Infrastructure.Tests/Squidex.Infrastructure.Tests.csproj @@ -30,7 +30,7 @@ - + all runtime; build; native; contentfiles; analyzers diff --git a/backend/tests/Squidex.Infrastructure.Tests/States/PersistenceEventSourcingTests.cs b/backend/tests/Squidex.Infrastructure.Tests/States/PersistenceEventSourcingTests.cs index b2bf50363..2be7bf0e8 100644 --- a/backend/tests/Squidex.Infrastructure.Tests/States/PersistenceEventSourcingTests.cs +++ b/backend/tests/Squidex.Infrastructure.Tests/States/PersistenceEventSourcingTests.cs @@ -19,7 +19,7 @@ public class PersistenceEventSourcingTests private readonly IEventStore eventStore = A.Fake(); private readonly IEventStreamNames eventStreamNames = A.Fake(); private readonly ISnapshotStore snapshotStore = A.Fake>(); - private readonly IStore sut; + private readonly Store sut; public PersistenceEventSourcingTests() { diff --git a/backend/tests/Squidex.Web.Tests/Squidex.Web.Tests.csproj b/backend/tests/Squidex.Web.Tests/Squidex.Web.Tests.csproj index 6bdf55416..67d466998 100644 --- a/backend/tests/Squidex.Web.Tests/Squidex.Web.Tests.csproj +++ b/backend/tests/Squidex.Web.Tests/Squidex.Web.Tests.csproj @@ -27,7 +27,7 @@ - + all runtime; build; native; contentfiles; analyzers diff --git a/tools/.editorconfig b/tools/.editorconfig index 2afa7cb97..274a6bc5a 100644 --- a/tools/.editorconfig +++ b/tools/.editorconfig @@ -27,9 +27,6 @@ dotnet_diagnostic.IDE0305.severity = none # CA1707: Identifiers should not contain underscores dotnet_diagnostic.CA1707.severity = none -# CA1861: Avoid constant arrays as arguments -dotnet_diagnostic.CA1861.severity = none - # CA2016: Forward the 'CancellationToken' parameter to methods dotnet_diagnostic.CA2016.severity = none @@ -187,4 +184,21 @@ dotnet_diagnostic.SA1623.severity = none dotnet_diagnostic.SYSLIB1045.severity = none # xUnit1033: Test classes decorated with 'Xunit.IClassFixture' or 'Xunit.ICollectionFixture' should add a constructor argument of type TFixture -dotnet_diagnostic.xUnit1033.severity = none \ No newline at end of file +dotnet_diagnostic.xUnit1033.severity = none + +# xUnit1051: Calls to methods which accept CancellationToken should use TestContext.Current.CancellationToken +dotnet_diagnostic.xUnit1051.severity = none + +[*Tests*.cs] +# MA0040: Forward the CancellationToken parameter to methods that take one +dotnet_diagnostic.MA0040.severity = none + +# xUnit1051: Calls to methods which accept CancellationToken should use TestContext.Current.CancellationToken +dotnet_diagnostic.xUnit1051.severity = none + +# CA1816: Dispose methods should call SuppressFinalize +dotnet_diagnostic.CA1816.severity = none + +[*Fixture.cs] +# CA1816: Dispose methods should call SuppressFinalize +dotnet_diagnostic.CA1816.severity = none \ No newline at end of file diff --git a/tools/TestSuite/TestSuite.ApiTests/ContentQueryFixture.cs b/tools/TestSuite/TestSuite.ApiTests/ContentQueryFixture.cs index ca1af6e07..8d6c4ed9d 100644 --- a/tools/TestSuite/TestSuite.ApiTests/ContentQueryFixture.cs +++ b/tools/TestSuite/TestSuite.ApiTests/ContentQueryFixture.cs @@ -20,7 +20,7 @@ public sealed class ContentQueryFixture : TestSchemaFixtureBase { } - public override async Task InitializeAsync() + public override async ValueTask InitializeAsync() { await base.InitializeAsync(); @@ -50,19 +50,19 @@ public sealed class ContentQueryFixture : TestSchemaFixtureBase String = index.ToString(CultureInfo.InvariantCulture), }; - await Contents.CreateAsync(data, ContentCreateOptions.AsPublish); + await Contents.CreateAsync(data, ContentCreateOptions.AsPublish, ct: TestContext.Current.CancellationToken); } } - public override async Task DisposeAsync() + public override async ValueTask DisposeAsync() { await base.DisposeAsync(); - var contents = await Contents.GetAsync(); + var contents = await Contents.GetAsync(ct: TestContext.Current.CancellationToken); foreach (var content in contents.Items) { - await Contents.DeleteAsync(content); + await Contents.DeleteAsync(content, ct: TestContext.Current.CancellationToken); } } } diff --git a/tools/TestSuite/TestSuite.ApiTests/GraphQLFixture.cs b/tools/TestSuite/TestSuite.ApiTests/GraphQLFixture.cs index 7702a3b90..6ba1c39dd 100644 --- a/tools/TestSuite/TestSuite.ApiTests/GraphQLFixture.cs +++ b/tools/TestSuite/TestSuite.ApiTests/GraphQLFixture.cs @@ -32,7 +32,7 @@ public sealed class GraphQLFixture : ContentFixture { } - public override async Task InitializeAsync() + public override async ValueTask InitializeAsync() { await base.InitializeAsync(); @@ -46,7 +46,7 @@ public sealed class GraphQLFixture : ContentFixture { try { - var response = await Client.Schemas.PostSchemaAsync(request); + var response = await Client.Schemas.PostSchemaAsync(request, TestContext.Current.CancellationToken); return response.Id; } @@ -57,7 +57,7 @@ public sealed class GraphQLFixture : ContentFixture throw; } - var schema = await Client.Schemas.GetSchemaAsync(request.Name); + var schema = await Client.Schemas.GetSchemaAsync(request.Name, TestContext.Current.CancellationToken); return schema.Id; } @@ -174,7 +174,7 @@ public sealed class GraphQLFixture : ContentFixture private async Task CreateContentsAsync() { - var countries = await Countries.GetAsync(); + var countries = await Countries.GetAsync(ct: TestContext.Current.CancellationToken); if (countries.Total > 0) { @@ -212,7 +212,7 @@ public sealed class GraphQLFixture : ContentFixture }, }; - var city = await Cities.CreateAsync(cityData, ContentCreateOptions.AsPublish); + var city = await Cities.CreateAsync(cityData, ContentCreateOptions.AsPublish, ct: TestContext.Current.CancellationToken); return city.Id; } @@ -231,7 +231,7 @@ public sealed class GraphQLFixture : ContentFixture }, }; - var state = await States.CreateAsync(stateData, ContentCreateOptions.AsPublish); + var state = await States.CreateAsync(stateData, ContentCreateOptions.AsPublish, ct: TestContext.Current.CancellationToken); return state.Id; } @@ -259,6 +259,6 @@ public sealed class GraphQLFixture : ContentFixture }, }; - await Countries.CreateAsync(countryData, ContentCreateOptions.AsPublish); + await Countries.CreateAsync(countryData, ContentCreateOptions.AsPublish, ct: TestContext.Current.CancellationToken); } } diff --git a/tools/TestSuite/TestSuite.ApiTests/TestSuite.ApiTests.csproj b/tools/TestSuite/TestSuite.ApiTests/TestSuite.ApiTests.csproj index ad98228d7..83d034775 100644 --- a/tools/TestSuite/TestSuite.ApiTests/TestSuite.ApiTests.csproj +++ b/tools/TestSuite/TestSuite.ApiTests/TestSuite.ApiTests.csproj @@ -19,8 +19,8 @@ - - + + all runtime; build; native; contentfiles; analyzers diff --git a/tools/TestSuite/TestSuite.LoadTests/ReadingBenchmarks.cs b/tools/TestSuite/TestSuite.LoadTests/ReadingBenchmarks.cs index 07802ed76..8514d902a 100644 --- a/tools/TestSuite/TestSuite.LoadTests/ReadingBenchmarks.cs +++ b/tools/TestSuite/TestSuite.LoadTests/ReadingBenchmarks.cs @@ -7,7 +7,6 @@ using TestSuite.Fixtures; using Xunit; -using Xunit.Abstractions; #pragma warning disable SA1300 // Element should begin with upper-case letter diff --git a/tools/TestSuite/TestSuite.LoadTests/ReadingFixture.cs b/tools/TestSuite/TestSuite.LoadTests/ReadingFixture.cs index 15ac4bbf5..22720a673 100644 --- a/tools/TestSuite/TestSuite.LoadTests/ReadingFixture.cs +++ b/tools/TestSuite/TestSuite.LoadTests/ReadingFixture.cs @@ -20,7 +20,7 @@ public sealed class ReadingFixture : TestSchemaFixtureBase { } - public override async Task InitializeAsync() + public override async ValueTask InitializeAsync() { await base.InitializeAsync(); @@ -54,7 +54,7 @@ public sealed class ReadingFixture : TestSchemaFixtureBase } } - public override async Task DisposeAsync() + public override async ValueTask DisposeAsync() { await base.DisposeAsync(); diff --git a/tools/TestSuite/TestSuite.LoadTests/Run.cs b/tools/TestSuite/TestSuite.LoadTests/Run.cs index dc6ce02fa..a13eab33c 100644 --- a/tools/TestSuite/TestSuite.LoadTests/Run.cs +++ b/tools/TestSuite/TestSuite.LoadTests/Run.cs @@ -8,7 +8,6 @@ using System.Collections.Concurrent; using System.Diagnostics; using Xunit; -using Xunit.Abstractions; namespace TestSuite.LoadTests; diff --git a/tools/TestSuite/TestSuite.LoadTests/TestSuite.LoadTests.csproj b/tools/TestSuite/TestSuite.LoadTests/TestSuite.LoadTests.csproj index c569ea175..c80b3ec73 100644 --- a/tools/TestSuite/TestSuite.LoadTests/TestSuite.LoadTests.csproj +++ b/tools/TestSuite/TestSuite.LoadTests/TestSuite.LoadTests.csproj @@ -13,7 +13,7 @@ - + all runtime; build; native; contentfiles; analyzers diff --git a/tools/TestSuite/TestSuite.Shared/Fixtures/ClientFixture.cs b/tools/TestSuite/TestSuite.Shared/Fixtures/ClientFixture.cs index 2b5e12cf0..a794471e9 100644 --- a/tools/TestSuite/TestSuite.Shared/Fixtures/ClientFixture.cs +++ b/tools/TestSuite/TestSuite.Shared/Fixtures/ClientFixture.cs @@ -90,7 +90,7 @@ public class ClientFixture : IAsyncLifetime return (client, await client.Apps.PostAppAsync(request)); } - public virtual async Task InitializeAsync() + public virtual async ValueTask InitializeAsync() { Squidex = await Factories.CreateAsync(nameof(ClientWrapper), async () => { @@ -102,8 +102,8 @@ public class ClientFixture : IAsyncLifetime }); } - public virtual Task DisposeAsync() + public virtual ValueTask DisposeAsync() { - return Task.CompletedTask; + return default; } } diff --git a/tools/TestSuite/TestSuite.Shared/Fixtures/CreatedAppFixture.cs b/tools/TestSuite/TestSuite.Shared/Fixtures/CreatedAppFixture.cs index 09961b067..a9da182a7 100644 --- a/tools/TestSuite/TestSuite.Shared/Fixtures/CreatedAppFixture.cs +++ b/tools/TestSuite/TestSuite.Shared/Fixtures/CreatedAppFixture.cs @@ -11,7 +11,7 @@ namespace TestSuite.Fixtures; public class CreatedAppFixture : ClientFixture { - public override async Task InitializeAsync() + public override async ValueTask InitializeAsync() { await base.InitializeAsync(); diff --git a/tools/TestSuite/TestSuite.Shared/Fixtures/CreatedTeamFixture.cs b/tools/TestSuite/TestSuite.Shared/Fixtures/CreatedTeamFixture.cs index 8cf0ff332..600cbec0d 100644 --- a/tools/TestSuite/TestSuite.Shared/Fixtures/CreatedTeamFixture.cs +++ b/tools/TestSuite/TestSuite.Shared/Fixtures/CreatedTeamFixture.cs @@ -17,7 +17,7 @@ public class CreatedTeamFixture : ClientFixture public TeamDto Team { get; private set; } - public override async Task InitializeAsync() + public override async ValueTask InitializeAsync() { await base.InitializeAsync(); diff --git a/tools/TestSuite/TestSuite.Shared/Fixtures/TestSchemaFixtureBase.cs b/tools/TestSuite/TestSuite.Shared/Fixtures/TestSchemaFixtureBase.cs index b400435b1..2af68a526 100644 --- a/tools/TestSuite/TestSuite.Shared/Fixtures/TestSchemaFixtureBase.cs +++ b/tools/TestSuite/TestSuite.Shared/Fixtures/TestSchemaFixtureBase.cs @@ -16,7 +16,7 @@ public abstract class TestSchemaFixtureBase(string schemaName) : CreatedAppFixtu public string SchemaName { get; } = schemaName; - public override async Task InitializeAsync() + public override async ValueTask InitializeAsync() { await base.InitializeAsync(); diff --git a/tools/TestSuite/TestSuite.Shared/Fixtures/TestSchemaWithReferencesFixtureBase.cs b/tools/TestSuite/TestSuite.Shared/Fixtures/TestSchemaWithReferencesFixtureBase.cs index b2439e12a..d501cfd2e 100644 --- a/tools/TestSuite/TestSuite.Shared/Fixtures/TestSchemaWithReferencesFixtureBase.cs +++ b/tools/TestSuite/TestSuite.Shared/Fixtures/TestSchemaWithReferencesFixtureBase.cs @@ -16,7 +16,7 @@ public abstract class TestSchemaWithReferencesFixtureBase(string schemaName) : C public string SchemaName { get; } = schemaName; - public override async Task InitializeAsync() + public override async ValueTask InitializeAsync() { await base.InitializeAsync(); diff --git a/tools/TestSuite/TestSuite.Shared/TestSuite.Shared.csproj b/tools/TestSuite/TestSuite.Shared/TestSuite.Shared.csproj index 82aee2ef0..ab8793629 100644 --- a/tools/TestSuite/TestSuite.Shared/TestSuite.Shared.csproj +++ b/tools/TestSuite/TestSuite.Shared/TestSuite.Shared.csproj @@ -22,7 +22,7 @@ - +