diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/AppClient.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/AppClient.cs index 403dff845..9f6f0ed73 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Apps/AppClient.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Apps/AppClient.cs @@ -6,6 +6,7 @@ // All rights reserved. // ========================================================================== +using System.Diagnostics.Contracts; using Squidex.Infrastructure; namespace Squidex.Domain.Apps.Core.Apps @@ -42,6 +43,7 @@ namespace Squidex.Domain.Apps.Core.Apps this.permission = permission; } + [Pure] public AppClient Update(AppClientPermission newPermission) { Guard.Enum(newPermission, nameof(newPermission)); @@ -49,6 +51,7 @@ namespace Squidex.Domain.Apps.Core.Apps return new AppClient(name, secret, newPermission); } + [Pure] public AppClient Rename(string newName) { Guard.NotNullOrEmpty(newName, nameof(newName)); diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/AppClients.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/AppClients.cs index e1ee6f933..bd606ea0d 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Apps/AppClients.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Apps/AppClients.cs @@ -7,6 +7,7 @@ // ========================================================================== using System.Collections.Immutable; +using System.Diagnostics.Contracts; using Squidex.Infrastructure; namespace Squidex.Domain.Apps.Core.Apps @@ -25,6 +26,7 @@ namespace Squidex.Domain.Apps.Core.Apps { } + [Pure] public AppClients Add(string id, AppClient client) { Guard.NotNullOrEmpty(id, nameof(id)); @@ -33,6 +35,7 @@ namespace Squidex.Domain.Apps.Core.Apps return new AppClients(Inner.Add(id, client)); } + [Pure] public AppClients Add(string id, string secret) { Guard.NotNullOrEmpty(id, nameof(id)); @@ -40,6 +43,7 @@ namespace Squidex.Domain.Apps.Core.Apps return new AppClients(Inner.Add(id, new AppClient(id, secret, AppClientPermission.Editor))); } + [Pure] public AppClients Revoke(string id) { Guard.NotNullOrEmpty(id, nameof(id)); @@ -47,6 +51,7 @@ namespace Squidex.Domain.Apps.Core.Apps return new AppClients(Inner.Remove(id)); } + [Pure] public AppClients Rename(string id, string newName) { Guard.NotNullOrEmpty(id, nameof(id)); @@ -59,6 +64,7 @@ namespace Squidex.Domain.Apps.Core.Apps return new AppClients(Inner.SetItem(id, client.Rename(newName))); } + [Pure] public AppClients Update(string id, AppClientPermission permission) { Guard.NotNullOrEmpty(id, nameof(id)); diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/AppContributors.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/AppContributors.cs index b9639881b..ffdd82c3f 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Apps/AppContributors.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Apps/AppContributors.cs @@ -7,6 +7,7 @@ // ========================================================================== using System.Collections.Immutable; +using System.Diagnostics.Contracts; using Squidex.Infrastructure; namespace Squidex.Domain.Apps.Core.Apps @@ -25,6 +26,7 @@ namespace Squidex.Domain.Apps.Core.Apps { } + [Pure] public AppContributors Assign(string contributorId, AppContributorPermission permission) { Guard.NotNullOrEmpty(contributorId, nameof(contributorId)); @@ -33,6 +35,7 @@ namespace Squidex.Domain.Apps.Core.Apps return new AppContributors(Inner.SetItem(contributorId, permission)); } + [Pure] public AppContributors Remove(string contributorId) { Guard.NotNullOrEmpty(contributorId, nameof(contributorId)); diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/LanguagesConfig.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/LanguagesConfig.cs index f5c262640..aa3a29666 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Apps/LanguagesConfig.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Apps/LanguagesConfig.cs @@ -10,6 +10,7 @@ using System; using System.Collections; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics.Contracts; using System.Linq; using Squidex.Infrastructure; @@ -88,6 +89,7 @@ namespace Squidex.Domain.Apps.Core.Apps return Build(languages?.Select(x => new LanguageConfig(x)).ToList()); } + [Pure] public LanguagesConfig MakeMaster(Language language) { Guard.NotNull(language, nameof(language)); @@ -95,6 +97,7 @@ namespace Squidex.Domain.Apps.Core.Apps return new LanguagesConfig(languages, languages[language]); } + [Pure] public LanguagesConfig Set(LanguageConfig config) { Guard.NotNull(config, nameof(config)); @@ -102,6 +105,7 @@ namespace Squidex.Domain.Apps.Core.Apps return new LanguagesConfig(languages.SetItem(config.Language, config), Master?.Language == config.Language ? config : Master); } + [Pure] public LanguagesConfig Remove(Language language) { Guard.NotNull(language, nameof(language)); diff --git a/src/Squidex.Domain.Apps.Core.Model/Rules/Rule.cs b/src/Squidex.Domain.Apps.Core.Model/Rules/Rule.cs index 1e7a900b7..7bec58f87 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Rules/Rule.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Rules/Rule.cs @@ -7,6 +7,7 @@ // ========================================================================== using System; +using System.Diagnostics.Contracts; using Squidex.Infrastructure; namespace Squidex.Domain.Apps.Core.Rules @@ -41,6 +42,7 @@ namespace Squidex.Domain.Apps.Core.Rules this.action = action; } + [Pure] public Rule Enable() { return Clone(clone => @@ -49,6 +51,7 @@ namespace Squidex.Domain.Apps.Core.Rules }); } + [Pure] public Rule Disable() { return Clone(clone => @@ -57,6 +60,7 @@ namespace Squidex.Domain.Apps.Core.Rules }); } + [Pure] public Rule Update(RuleTrigger newTrigger) { Guard.NotNull(newTrigger, nameof(newTrigger)); @@ -72,6 +76,7 @@ namespace Squidex.Domain.Apps.Core.Rules }); } + [Pure] public Rule Update(RuleAction newAction) { Guard.NotNull(newAction, nameof(newAction)); diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs index f969b6603..c4de1e7f1 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs @@ -48,5 +48,10 @@ namespace Squidex.Domain.Apps.Core.Schemas { return visitor.Visit(this); } + + public override Field CreateField(long id, string name, Partitioning partitioning) + { + return new AssetsField(id, name, partitioning, this); + } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/BooleanFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/BooleanFieldProperties.cs index cbd54521b..c6817f309 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/BooleanFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/BooleanFieldProperties.cs @@ -48,5 +48,10 @@ namespace Squidex.Domain.Apps.Core.Schemas { return visitor.Visit(this); } + + public override Field CreateField(long id, string name, Partitioning partitioning) + { + return new BooleanField(id, name, partitioning, this); + } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/DateTimeFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/DateTimeFieldProperties.cs index 982de7e40..382fc8430 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/DateTimeFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/DateTimeFieldProperties.cs @@ -94,5 +94,10 @@ namespace Squidex.Domain.Apps.Core.Schemas { return visitor.Visit(this); } + + public override Field CreateField(long id, string name, Partitioning partitioning) + { + return new DateTimeField(id, name, partitioning, this); + } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldProperties.cs index 315dfc925..aa530df70 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldProperties.cs @@ -57,5 +57,7 @@ namespace Squidex.Domain.Apps.Core.Schemas } public abstract T Accept(IFieldPropertiesVisitor visitor); + + public abstract Field CreateField(long id, string name, Partitioning partitioning); } } \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldRegistry.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldRegistry.cs index 710581ef1..5c6cecb70 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldRegistry.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldRegistry.cs @@ -17,29 +17,7 @@ namespace Squidex.Domain.Apps.Core.Schemas private delegate Field FactoryFunction(long id, string name, Partitioning partitioning, FieldProperties properties); private readonly TypeNameRegistry typeNameRegistry; - private readonly Dictionary fieldsByPropertyType = new Dictionary(); - - private sealed class Registered - { - private readonly FactoryFunction fieldFactory; - private readonly Type propertiesType; - - public Type PropertiesType - { - get { return propertiesType; } - } - - public Registered(FactoryFunction fieldFactory, Type propertiesType) - { - this.fieldFactory = fieldFactory; - this.propertiesType = propertiesType; - } - - public Field CreateField(long id, string name, Partitioning partitioning, FieldProperties properties) - { - return fieldFactory(id, name, partitioning, properties); - } - } + private readonly Dictionary fieldsByPropertyType = new Dictionary(); public FieldRegistry(TypeNameRegistry typeNameRegistry) { @@ -47,69 +25,39 @@ namespace Squidex.Domain.Apps.Core.Schemas this.typeNameRegistry = typeNameRegistry; - Add( - (id, name, partitioning, properties) => - new BooleanField(id, name, partitioning, (BooleanFieldProperties)properties)); - - Add( - (id, name, partitioning, properties) => - new NumberField(id, name, partitioning, (NumberFieldProperties)properties)); - - Add( - (id, name, partitioning, properties) => - new StringField(id, name, partitioning, (StringFieldProperties)properties)); - - Add( - (id, name, partitioning, properties) => - new JsonField(id, name, partitioning, (JsonFieldProperties)properties)); - - Add( - (id, name, partitioning, properties) => - new AssetsField(id, name, partitioning, (AssetsFieldProperties)properties)); - - Add( - (id, name, partitioning, properties) => - new GeolocationField(id, name, partitioning, (GeolocationFieldProperties)properties)); - - Add( - (id, name, partitioning, properties) => - new ReferencesField(id, name, partitioning, (ReferencesFieldProperties)properties)); - - Add( - (id, name, partitioning, properties) => - new DateTimeField(id, name, partitioning, (DateTimeFieldProperties)properties)); - - Add( - (id, name, partitioning, properties) => - new TagsField(id, name, partitioning, (TagsFieldProperties)properties)); + RegisterField(); + RegisterField(); + RegisterField(); + RegisterField(); + RegisterField(); + RegisterField(); + RegisterField(); + RegisterField(); + RegisterField(); typeNameRegistry.MapObsolete(typeof(ReferencesFieldProperties), "DateTime"); typeNameRegistry.MapObsolete(typeof(DateTimeFieldProperties), "References"); } - private void Add(FactoryFunction fieldFactory) + private void RegisterField() { - Guard.NotNull(fieldFactory, nameof(fieldFactory)); - - typeNameRegistry.Map(typeof(TFieldProperties)); - - var registered = new Registered(fieldFactory, typeof(TFieldProperties)); + typeNameRegistry.Map(typeof(T)); - fieldsByPropertyType[registered.PropertiesType] = registered; + fieldsByPropertyType[typeof(T)] = (id, name, partitioning, properties) => properties.CreateField(id, name, partitioning); } public Field CreateField(long id, string name, Partitioning partitioning, FieldProperties properties) { Guard.NotNull(properties, nameof(properties)); - var registered = fieldsByPropertyType.GetOrDefault(properties.GetType()); + var factory = fieldsByPropertyType.GetOrDefault(properties.GetType()); - if (registered == null) + if (factory == null) { throw new InvalidOperationException($"The field property '{properties.GetType()}' is not supported."); } - return registered.CreateField(id, name, partitioning, properties); + return factory(id, name, partitioning, properties); } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/GeolocationFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/GeolocationFieldProperties.cs index e82e6ab89..e01fddcb4 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/GeolocationFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/GeolocationFieldProperties.cs @@ -33,5 +33,10 @@ namespace Squidex.Domain.Apps.Core.Schemas { return visitor.Visit(this); } + + public override Field CreateField(long id, string name, Partitioning partitioning) + { + return new GeolocationField(id, name, partitioning, this); + } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/JsonFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/JsonFieldProperties.cs index c432be09a..5c4ffd918 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/JsonFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/JsonFieldProperties.cs @@ -17,5 +17,10 @@ namespace Squidex.Domain.Apps.Core.Schemas { return visitor.Visit(this); } + + public override Field CreateField(long id, string name, Partitioning partitioning) + { + return new JsonField(id, name, partitioning, this); + } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs index 2fe90fd73..f7d6af843 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs @@ -94,5 +94,10 @@ namespace Squidex.Domain.Apps.Core.Schemas { return visitor.Visit(this); } + + public override Field CreateField(long id, string name, Partitioning partitioning) + { + return new NumberField(id, name, partitioning, this); + } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs index bfc5119a0..3faa12a26 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs @@ -64,5 +64,10 @@ namespace Squidex.Domain.Apps.Core.Schemas { return visitor.Visit(this); } + + public override Field CreateField(long id, string name, Partitioning partitioning) + { + return new ReferencesField(id, name, partitioning, this); + } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs index 849ac97a8..80c2d6cbc 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs @@ -124,5 +124,10 @@ namespace Squidex.Domain.Apps.Core.Schemas { return visitor.Visit(this); } + + public override Field CreateField(long id, string name, Partitioning partitioning) + { + return new StringField(id, name, partitioning, this); + } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs index 99b48b2d3..579c65ca5 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs @@ -48,5 +48,10 @@ namespace Squidex.Domain.Apps.Core.Schemas { return visitor.Visit(this); } + + public override Field CreateField(long id, string name, Partitioning partitioning) + { + return new TagsField(id, name, partitioning, this); + } } } diff --git a/src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonConvention.cs b/src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonConvention.cs index 62f163f47..b9964135e 100644 --- a/src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonConvention.cs +++ b/src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonConvention.cs @@ -27,7 +27,7 @@ namespace Squidex.Infrastructure.MongoDb if (attributes.OfType().Any()) { - var bsonSerializerType = typeof(JsonBsonSerializer<>).MakeGenericType(memberMap.MemberType); + var bsonSerializerType = typeof(BsonJsonSerializer<>).MakeGenericType(memberMap.MemberType); var bsonSerializer = Activator.CreateInstance(bsonSerializerType, serializer); memberMap.SetSerializer((IBsonSerializer)bsonSerializer); diff --git a/src/Squidex.Infrastructure.MongoDb/MongoDb/JsonBsonConverter.cs b/src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonConverter.cs similarity index 98% rename from src/Squidex.Infrastructure.MongoDb/MongoDb/JsonBsonConverter.cs rename to src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonConverter.cs index 4ff5b988c..20ec6e1ee 100644 --- a/src/Squidex.Infrastructure.MongoDb/MongoDb/JsonBsonConverter.cs +++ b/src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonConverter.cs @@ -1,5 +1,5 @@ // ========================================================================== -// JsonBsonConverter.cs +// BsonJsonConverter.cs // Squidex Headless CMS // ========================================================================== // Copyright (c) Squidex Group @@ -12,7 +12,7 @@ using Newtonsoft.Json.Linq; namespace Squidex.Infrastructure.MongoDb { - public static class JsonBsonConverter + public static class BsonJsonConverter { public static BsonDocument ToBson(this JObject source) { diff --git a/src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonReader.cs b/src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonReader.cs index ef0e6621e..bd7003da0 100644 --- a/src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonReader.cs +++ b/src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonReader.cs @@ -27,7 +27,9 @@ namespace Squidex.Infrastructure.MongoDb public override bool Read() { - if (bsonReader.State == BsonReaderState.Type) + if (bsonReader.State == BsonReaderState.Initial || + bsonReader.State == BsonReaderState.ScopeDocument || + bsonReader.State == BsonReaderState.Type) { bsonReader.ReadBsonType(); } @@ -60,9 +62,11 @@ namespace Squidex.Infrastructure.MongoDb break; case BsonType.Undefined: SetToken(NewtonsoftJsonToken.Undefined); + bsonReader.ReadUndefined(); break; case BsonType.Null: SetToken(NewtonsoftJsonToken.Null); + bsonReader.ReadNull(); break; case BsonType.String: SetToken(NewtonsoftJsonToken.String, bsonReader.ReadString()); @@ -93,6 +97,11 @@ namespace Squidex.Infrastructure.MongoDb } } + if (bsonReader.State == BsonReaderState.Initial) + { + return true; + } + return !bsonReader.IsAtEndOfFile(); } } diff --git a/src/Squidex.Infrastructure.MongoDb/MongoDb/JsonBsonSerializer.cs b/src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonSerializer.cs similarity index 90% rename from src/Squidex.Infrastructure.MongoDb/MongoDb/JsonBsonSerializer.cs rename to src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonSerializer.cs index c6a77df80..f19987464 100644 --- a/src/Squidex.Infrastructure.MongoDb/MongoDb/JsonBsonSerializer.cs +++ b/src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonSerializer.cs @@ -14,11 +14,11 @@ using Newtonsoft.Json.Linq; namespace Squidex.Infrastructure.MongoDb { - public class JsonBsonSerializer : ClassSerializerBase where T : class + public class BsonJsonSerializer : ClassSerializerBase where T : class { private readonly JsonSerializer serializer; - public JsonBsonSerializer(JsonSerializer serializer) + public BsonJsonSerializer(JsonSerializer serializer) { Guard.NotNull(serializer, nameof(serializer)); diff --git a/src/Squidex.Infrastructure.MongoDb/States/MongoStateStore.cs b/src/Squidex.Infrastructure.MongoDb/States/MongoStateStore.cs index c494e4054..d65bc6416 100644 --- a/src/Squidex.Infrastructure.MongoDb/States/MongoStateStore.cs +++ b/src/Squidex.Infrastructure.MongoDb/States/MongoStateStore.cs @@ -62,12 +62,13 @@ namespace Squidex.Infrastructure.States try { - await collection.InsertOneAsync( - /*Builders>.Filter.And( - Builders>.Filter.Eq(nameof(MongoState.Id), key), - Builders>.Filter.Eq(nameof(MongoState.Etag), oldEtag) - ),*/ - new MongoState { Id = key, Etag = newEtag, Doc = value }); + await collection.UpdateOneAsync( + Builders>.Filter.And( + Builders>.Filter.Eq(x => x.Id, key), + Builders>.Filter.Eq(x => x.Etag, oldEtag) + ), + Builders>.Update.Set(x => x.Doc, value), + Upsert); } catch (MongoWriteException ex) { diff --git a/tests/Benchmarks/IBenchmark.cs b/tests/Benchmarks/Benchmark.cs similarity index 54% rename from tests/Benchmarks/IBenchmark.cs rename to tests/Benchmarks/Benchmark.cs index 779531450..2bf549ceb 100644 --- a/tests/Benchmarks/IBenchmark.cs +++ b/tests/Benchmarks/Benchmark.cs @@ -8,12 +8,24 @@ namespace Benchmarks { - public interface IBenchmark + public abstract class Benchmark { - void RunInitialize(); + public virtual void Initialize() + { + } - long Run(); + public virtual void RunInitialize() + { + } - void RunCleanup(); + public virtual void RunCleanup() + { + } + + public virtual void Cleanup() + { + } + + public abstract long Run(); } } diff --git a/tests/Benchmarks/Program.cs b/tests/Benchmarks/Program.cs index 2e408b32e..c04991e0f 100644 --- a/tests/Benchmarks/Program.cs +++ b/tests/Benchmarks/Program.cs @@ -16,7 +16,7 @@ namespace Benchmarks { public static class Program { - private static readonly List<(string Name, IBenchmark Benchmark)> Benchmarks = new IBenchmark[] + private static readonly List<(string Name, Benchmark Benchmark)> Benchmarks = new Benchmark[] { new AppendToEventStore(), new AppendToEventStoreWithManyWriters(), @@ -51,6 +51,8 @@ namespace Benchmarks Console.WriteLine($"{selected.Name}: Initialized"); + selected.Benchmark.Initialize(); + for (var run = 0; run < numRuns; run++) { try @@ -82,6 +84,10 @@ namespace Benchmarks { Console.WriteLine($"Benchmark failed with '{e.Message}'"); } + finally + { + selected.Benchmark.Cleanup(); + } } Console.ReadLine(); diff --git a/tests/Benchmarks/Tests/AppendToEventStore.cs b/tests/Benchmarks/Tests/AppendToEventStore.cs index 16cc26ea7..d33e20cde 100644 --- a/tests/Benchmarks/Tests/AppendToEventStore.cs +++ b/tests/Benchmarks/Tests/AppendToEventStore.cs @@ -13,19 +13,19 @@ using Squidex.Infrastructure.CQRS.Events; namespace Benchmarks.Tests { - public sealed class AppendToEventStore : IBenchmark + public sealed class AppendToEventStore : Benchmark { private IServiceProvider services; private IEventStore eventStore; - public void RunInitialize() + public override void RunInitialize() { services = Services.Create(); eventStore = services.GetRequiredService(); } - public long Run() + public override long Run() { const long numCommits = 100; const long numStreams = 20; @@ -45,7 +45,7 @@ namespace Benchmarks.Tests return numCommits * numStreams; } - public void RunCleanup() + public override void RunCleanup() { services.Cleanup(); } diff --git a/tests/Benchmarks/Tests/AppendToEventStoreWithManyWriters.cs b/tests/Benchmarks/Tests/AppendToEventStoreWithManyWriters.cs index 307f52cd5..ede647b4f 100644 --- a/tests/Benchmarks/Tests/AppendToEventStoreWithManyWriters.cs +++ b/tests/Benchmarks/Tests/AppendToEventStoreWithManyWriters.cs @@ -14,19 +14,19 @@ using Squidex.Infrastructure.CQRS.Events; namespace Benchmarks.Tests { - public sealed class AppendToEventStoreWithManyWriters : IBenchmark + public sealed class AppendToEventStoreWithManyWriters : Benchmark { private IServiceProvider services; private IEventStore eventStore; - public void RunInitialize() + public override void RunInitialize() { services = Services.Create(); eventStore = services.GetRequiredService(); } - public long Run() + public override long Run() { const long numCommits = 200; const long numStreams = 100; @@ -44,7 +44,7 @@ namespace Benchmarks.Tests return numCommits * numStreams; } - public void RunCleanup() + public override void RunCleanup() { services.Cleanup(); } diff --git a/tests/Benchmarks/Tests/HandleEvents.cs b/tests/Benchmarks/Tests/HandleEvents.cs index 121de4b25..a9c060ce3 100644 --- a/tests/Benchmarks/Tests/HandleEvents.cs +++ b/tests/Benchmarks/Tests/HandleEvents.cs @@ -15,7 +15,7 @@ using Squidex.Infrastructure.States; namespace Benchmarks.Tests { - public sealed class HandleEvents : IBenchmark + public sealed class HandleEvents : Benchmark { private const int NumEvents = 5000; private IServiceProvider services; @@ -24,7 +24,7 @@ namespace Benchmarks.Tests private EventDataFormatter eventDataFormatter; private MyEventConsumer eventConsumer; - public void RunInitialize() + public override void RunInitialize() { services = Services.Create(); @@ -39,7 +39,7 @@ namespace Benchmarks.Tests eventConsumerActor.Activate(eventConsumer); } - public long Run() + public override long Run() { var streamName = Guid.NewGuid().ToString(); @@ -55,7 +55,7 @@ namespace Benchmarks.Tests return NumEvents; } - public void RunCleanup() + public override void RunCleanup() { services.Cleanup(); } diff --git a/tests/Benchmarks/Tests/HandleEventsWithManyWriters.cs b/tests/Benchmarks/Tests/HandleEventsWithManyWriters.cs index 63d98da39..b76640717 100644 --- a/tests/Benchmarks/Tests/HandleEventsWithManyWriters.cs +++ b/tests/Benchmarks/Tests/HandleEventsWithManyWriters.cs @@ -16,7 +16,7 @@ using Squidex.Infrastructure.States; namespace Benchmarks.Tests { - public sealed class HandleEventsWithManyWriters : IBenchmark + public sealed class HandleEventsWithManyWriters : Benchmark { private const int NumCommits = 200; private const int NumStreams = 10; @@ -26,7 +26,7 @@ namespace Benchmarks.Tests private EventDataFormatter eventDataFormatter; private MyEventConsumer eventConsumer; - public void RunInitialize() + public override void RunInitialize() { services = Services.Create(); @@ -41,7 +41,7 @@ namespace Benchmarks.Tests eventConsumerActor.Activate(eventConsumer); } - public long Run() + public override long Run() { Parallel.For(0, NumStreams, streamId => { @@ -62,7 +62,7 @@ namespace Benchmarks.Tests return NumStreams * NumCommits; } - public void RunCleanup() + public override void RunCleanup() { services.Cleanup(); } diff --git a/tests/Benchmarks/Tests/ReadSchemaState.cs b/tests/Benchmarks/Tests/ReadSchemaState.cs index f0b63e25b..e12dcfa33 100644 --- a/tests/Benchmarks/Tests/ReadSchemaState.cs +++ b/tests/Benchmarks/Tests/ReadSchemaState.cs @@ -22,12 +22,12 @@ using Squidex.Infrastructure.States; namespace Benchmarks.Tests { - public class ReadSchemaState : IBenchmark + public class ReadSchemaState : Benchmark { private IServiceProvider services; private MyAppState grain; - public void RunInitialize() + public override void Initialize() { services = Services.Create(); @@ -84,7 +84,7 @@ namespace Benchmarks.Tests grain.WriteStateAsync().Wait(); } - public long Run() + public override long Run() { for (var i = 0; i < 10; i++) { @@ -94,7 +94,7 @@ namespace Benchmarks.Tests return 10; } - public void RunCleanup() + public override void Cleanup() { services.Cleanup(); } diff --git a/tests/Squidex.Infrastructure.Tests/MongoDb/BsonConverterTests.cs b/tests/Squidex.Infrastructure.Tests/MongoDb/BsonConverterTests.cs index 51bbd15e3..28ebd4b73 100644 --- a/tests/Squidex.Infrastructure.Tests/MongoDb/BsonConverterTests.cs +++ b/tests/Squidex.Infrastructure.Tests/MongoDb/BsonConverterTests.cs @@ -7,7 +7,11 @@ // ========================================================================== using System; +using System.IO; +using System.Linq; using FluentAssertions; +using MongoDB.Bson.IO; +using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Xunit; @@ -19,14 +23,30 @@ namespace Squidex.Infrastructure.MongoDb { public class TestObject { - public TimeSpan TimeSpan { get; set; } + public bool Bool { get; set; } + + public byte Byte { get; set; } + + public byte[] Bytes { get; set; } + + public string String { get; set; } + + public string[] Strings { get; set; } + + public float Float32 { get; set; } + + public double Float64 { get; set; } + + public Uri Uri { get; set; } public Guid Guid { get; set; } - public DateTimeOffset DateTimeOffset { get; set; } + public TimeSpan TimeSpan { get; set; } public DateTime DateTime { get; set; } + public DateTimeOffset DateTimeOffset { get; set; } + public Int64 Int64 { get; set; } public Int32 Int32 { get; set; } @@ -39,25 +59,13 @@ namespace Squidex.Infrastructure.MongoDb public UInt16 UInt16 { get; set; } - public double Float64 { get; set; } - - public float Float32 { get; set; } + public TestObject Nested { get; set; } - public bool Bool { get; set; } - - public byte Byte { get; set; } + public TestObject[] NestedArray { get; set; } - public byte[] Bytes { get; set; } - - public string String { get; set; } - - public string[] Strings { get; set; } - - public Uri Uri { get; set; } - - public static TestObject CreateWithValues() + public static TestObject CreateWithValues(bool nested = true) { - return new TestObject + var result = new TestObject { Bool = true, Byte = 0x2, @@ -78,16 +86,48 @@ namespace Squidex.Infrastructure.MongoDb UInt16 = 116, Uri = new Uri("http://squidex.io") }; + + if (nested) + { + result.Nested = CreateWithValues(false); + result.NestedArray = Enumerable.Repeat(0, 4).Select(x => CreateWithValues(false)).ToArray(); + } + + return result; } } + private readonly TestObject source = TestObject.CreateWithValues(); + private readonly JsonSerializer serializer = JsonSerializer.CreateDefault(); + [Fact] public void Should_serialize_and_deserialize_to_bson_with_json() { - var source = TestObject.CreateWithValues(); var target = JObject.FromObject(source).ToBson().ToJson().ToObject(); target.ShouldBeEquivalentTo(source); } + + [Fact] + public void Should_serialize_with_reader_and_writer() + { + var stream = new MemoryStream(); + + using (var writer = new BsonJsonWriter(new BsonBinaryWriter(stream))) + { + serializer.Serialize(writer, source); + + writer.Flush(); + } + + stream.Position = 0; + + using (var reader = new BsonJsonReader(new BsonBinaryReader(stream))) + { + var target = serializer.Deserialize(reader); + + target.ShouldBeEquivalentTo(source); + } + } } }